diff --git a/architecture/wwise.cpp b/architecture/wwise.cpp index f4328e4ff0..620efd4a7c 100644 --- a/architecture/wwise.cpp +++ b/architecture/wwise.cpp @@ -8,16 +8,16 @@ static mydsp m_dsp; static MapUI map_ui; -void initDSP(int sampleRate) { +inline void initDSP(int sampleRate) { m_dsp.init(sampleRate); m_dsp.buildUserInterface(&map_ui); } template // for the shake of proper usage and to supress a probable warning -void setParameter(const char* name, T value) { +inline void setParameter(const char* name, T value) { map_ui.setParamValue(std::string(name), static_cast(value)); } -FAUSTFLOAT getParameter(const char* name) { // Not used. Added for potential future debugging of the parameter's integration +inline FAUSTFLOAT getParameter(const char* name) { // Not used. Added for potential future debugging of the parameter's integration return map_ui.getParamValue(std::string(name)); } \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/.gitignore b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/.gitignore new file mode 100644 index 0000000000..a34a700e6f --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/.gitignore @@ -0,0 +1,481 @@ + +# Created by https://www.gitignore.io/api/archives,linux,xcode,macos,windows,visualstudio,premake-gmake + +.vscode + +### Archives ### +# It's better to unpack these files and commit the raw source because +# git has its own built in compression methods. +*.7z +*.jar +*.rar +*.zip +*.gz +*.tgz +*.bzip +*.bz2 +*.xz +*.lzma +*.cab + +# Packing-only formats +*.iso +*.tar + +# Package management formats +*.dmg +*.xpi +*.gem +*.egg +*.deb +*.rpm +*.msi +*.msm +*.msp +bundle.json + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### premake-gmake ### +Makefile +*.make +obj/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +### Xcode Patch ### +*.xcodeproj/* +/*.gcno + +### VisualStudio ### +## 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 +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Bb]uild/ +[Bb]uilds/ + +# 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 + +# 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/ + +# StyleCop +StyleCopReport.xml + +# Visual Studio project files +*.sln +*.vcxproj +*.vcxproj.filters + +# 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 + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# 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 +# 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 + +# 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 + +# 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/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# 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/ + +# End of https://www.gitignore.io/api/archives,linux,xcode,macos,windows,visualstudio,premake-gmake diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FactoryAssets/Manifest.xml b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FactoryAssets/Manifest.xml new file mode 100644 index 0000000000..87f94562c9 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FactoryAssets/Manifest.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/complexRain.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/complexRain.cpp new file mode 100644 index 0000000000..e5041dbbf6 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/complexRain.cpp @@ -0,0 +1,561 @@ +/* ------------------------------------------------------------ +name: "untitled" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __ComplexRain_H__ +#define __ComplexRain_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS ComplexRain +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +class ComplexRainSIG0 { + + private: + + int iVec2[2]; + int iRec10[2]; + + public: + + int getNumInputsComplexRainSIG0() { + return 0; + } + int getNumOutputsComplexRainSIG0() { + return 1; + } + + void instanceInitComplexRainSIG0(int sample_rate) { + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + iVec2[l6] = 0; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + iRec10[l7] = 0; + } + } + + void fillComplexRainSIG0(int count, float* table) { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iVec2[0] = 1; + iRec10[0] = (iVec2[1] + iRec10[1]) % 65536; + table[i1] = std::sin(9.58738e-05f * float(iRec10[0])); + iVec2[1] = iVec2[0]; + iRec10[1] = iRec10[0]; + } + } + +}; + +static ComplexRainSIG0* newComplexRainSIG0() { return (ComplexRainSIG0*)new ComplexRainSIG0(); } +static void deleteComplexRainSIG0(ComplexRainSIG0* dsp) { delete dsp; } + +static float ComplexRain_faustpower2_f(float value) { + return value * value; +} +static float ComplexRain_faustpower4_f(float value) { + return value * value * value * value; +} +static float ftbl0ComplexRainSIG0[65536]; + +class ComplexRain : public dsp { + + private: + + int iVec0[2]; + float fRec0[2]; + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + float fConst3; + float fConst4; + float fConst5; + float fConst6; + float fConst7; + float fConst8; + float fConst9; + int iRec3[2]; + float fRec2[3]; + float fConst10; + float fVec1[2]; + float fConst11; + float fConst12; + float fRec1[2]; + float fConst13; + float fRec11[2]; + float fConst14; + float fConst15; + float fConst16; + float fConst17; + float fConst18; + float fConst19; + float fConst20; + float fConst21; + float fConst22; + float fConst23; + float fConst24; + float fConst25; + float fConst26; + float fConst27; + float fConst28; + int iRec19[2]; + float fRec18[3]; + float fVec3[2]; + float fConst29; + float fConst30; + float fRec17[2]; + float fConst31; + float fRec16[2]; + float fVec4[2]; + float fConst32; + float fRec15[2]; + float fRec14[2]; + float fConst33; + float fConst34; + float fConst35; + float fRec13[2]; + int IOTA0; + float fVec5[512]; + int iConst36; + float fRec12[3]; + float fConst37; + float fRec7[2]; + float fConst38; + float fRec29[2]; + float fConst39; + float fConst40; + float fConst41; + float fConst42; + float fConst43; + float fConst44; + float fRec30[3]; + float fConst45; + float fRec4[2]; + float fConst46; + float fRec34[2]; + float fConst47; + float fConst48; + float fConst49; + float fConst50; + float fConst51; + float fConst52; + float fVec6[512]; + int iConst53; + float fRec35[3]; + float fConst54; + float fRec31[2]; + float fConst55; + float fRec36[2]; + float fConst56; + float fConst57; + float fConst58; + float fConst59; + float fConst60; + float fConst61; + float fRec37[3]; + float fConst62; + float fRec5[2]; + float fRec38[2]; + + public: + ComplexRain() { + } + + void metadata(Meta* m) { + m->declare("aanl.lib/name", "Faust Antialiased Nonlinearities"); + m->declare("aanl.lib/version", "1.4.1"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("delays.lib/name", "Faust Delay Library"); + m->declare("delays.lib/version", "1.1.0"); + m->declare("filename", "untitled.dsp"); + m->declare("filters.lib/fir:author", "Julius O. Smith III"); + m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/highpass:author", "Julius O. Smith III"); + m->declare("filters.lib/highpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/iir:author", "Julius O. Smith III"); + m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license"); + m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III"); + m->declare("filters.lib/lowpass:author", "Julius O. Smith III"); + m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/name", "Faust Filters Library"); + m->declare("filters.lib/resonbp:author", "Julius O. Smith III"); + m->declare("filters.lib/resonbp:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/resonbp:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf1:author", "Julius O. Smith III"); + m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf1s:author", "Julius O. Smith III"); + m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf2:author", "Julius O. Smith III"); + m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf2s:author", "Julius O. Smith III"); + m->declare("filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf2s:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/version", "1.7.1"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("noises.lib/name", "Faust Noise Generator Library"); + m->declare("noises.lib/version", "1.4.1"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/version", "1.6.0"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "1.6.0"); + m->declare("spats.lib/name", "Faust Spatialization Library"); + m->declare("spats.lib/spat:author", "Laurent Pottier, revised by Romain Michon"); + m->declare("spats.lib/version", "1.2.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 2; + } + + static void classInit(int sample_rate) { + ComplexRainSIG0* sig0 = newComplexRainSIG0(); + sig0->instanceInitComplexRainSIG0(sample_rate); + sig0->fillComplexRainSIG0(65536, ftbl0ComplexRainSIG0); + deleteComplexRainSIG0(sig0); + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = std::tan(6283.1855f / fConst0); + fConst2 = 1.0f / fConst1; + fConst3 = 1.0f - fConst2; + fConst4 = std::tan(31.415926f / fConst0); + fConst5 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst4)); + fConst6 = 1.0f / fConst4; + fConst7 = (fConst6 + -76.92308f) / fConst4 + 1.0f; + fConst8 = (fConst6 + 76.92308f) / fConst4 + 1.0f; + fConst9 = 1.0f / fConst8; + fConst10 = 2e+02f / (fConst4 * fConst8); + fConst11 = 0.1f / fConst1; + fConst12 = 1.0f / (fConst2 + 1.0f); + fConst13 = 669.0f / fConst0; + fConst14 = std::tan(6264.336f / fConst0); + fConst15 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst14)); + fConst16 = 1.0f / fConst14; + fConst17 = (fConst16 + -0.4347826f) / fConst14 + 1.0f; + fConst18 = (fConst16 + 0.4347826f) / fConst14 + 1.0f; + fConst19 = 1.0f / fConst18; + fConst20 = std::tan(1570.7964f / fConst0); + fConst21 = 1.0f / fConst20; + fConst22 = 1.0f - fConst21; + fConst23 = std::tan(157.07964f / fConst0); + fConst24 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst23)); + fConst25 = 1.0f / fConst23; + fConst26 = 1.0f - (1.0f - fConst25) / fConst23; + fConst27 = (fConst25 + 1.0f) / fConst23 + 1.0f; + fConst28 = 1.0f / fConst27; + fConst29 = 2.0f / (fConst23 * fConst27); + fConst30 = 1.0f / (fConst21 + 1.0f); + fConst31 = 1.0f / fConst0; + fConst32 = 0.5f / fConst20; + fConst33 = 1.0f / std::tan(28274.334f / fConst0); + fConst34 = 1.0f - fConst33; + fConst35 = 1.0f / (fConst33 + 1.0f); + iConst36 = int(std::min(3e+02f, std::max(0.0f, 0.0037f * fConst0))); + fConst37 = 1.0f / (fConst14 * fConst18); + fConst38 = 254.0f / fConst0; + fConst39 = std::tan(6305.1763f / fConst0); + fConst40 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst39)); + fConst41 = 1.0f / fConst39; + fConst42 = (fConst41 + -0.4347826f) / fConst39 + 1.0f; + fConst43 = (fConst41 + 0.4347826f) / fConst39 + 1.0f; + fConst44 = 1.0f / fConst43; + fConst45 = 1.0f / (fConst39 * fConst43); + fConst46 = 551.0f / fConst0; + fConst47 = std::tan(6185.796f / fConst0); + fConst48 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst47)); + fConst49 = 1.0f / fConst47; + fConst50 = (fConst49 + -0.4347826f) / fConst47 + 1.0f; + fConst51 = (fConst49 + 0.4347826f) / fConst47 + 1.0f; + fConst52 = 1.0f / fConst51; + iConst53 = int(std::min(3e+02f, std::max(0.0f, 0.0042f * fConst0))); + fConst54 = 1.0f / (fConst47 * fConst51); + fConst55 = 443.0f / fConst0; + fConst56 = std::tan(6239.203f / fConst0); + fConst57 = 2.0f * (1.0f - 1.0f / ComplexRain_faustpower2_f(fConst56)); + fConst58 = 1.0f / fConst56; + fConst59 = (fConst58 + -0.4347826f) / fConst56 + 1.0f; + fConst60 = (fConst58 + 0.4347826f) / fConst56 + 1.0f; + fConst61 = 1.0f / fConst60; + fConst62 = 1.0f / (fConst56 * fConst60); + } + + virtual void instanceResetUserInterface() { + } + + virtual void instanceClear() { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + fRec0[l1] = 0.0f; + } + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + iRec3[l2] = 0; + } + for (int l3 = 0; l3 < 3; l3 = l3 + 1) { + fRec2[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + fVec1[l4] = 0.0f; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + fRec1[l5] = 0.0f; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec11[l8] = 0.0f; + } + for (int l9 = 0; l9 < 2; l9 = l9 + 1) { + iRec19[l9] = 0; + } + for (int l10 = 0; l10 < 3; l10 = l10 + 1) { + fRec18[l10] = 0.0f; + } + for (int l11 = 0; l11 < 2; l11 = l11 + 1) { + fVec3[l11] = 0.0f; + } + for (int l12 = 0; l12 < 2; l12 = l12 + 1) { + fRec17[l12] = 0.0f; + } + for (int l13 = 0; l13 < 2; l13 = l13 + 1) { + fRec16[l13] = 0.0f; + } + for (int l14 = 0; l14 < 2; l14 = l14 + 1) { + fVec4[l14] = 0.0f; + } + for (int l15 = 0; l15 < 2; l15 = l15 + 1) { + fRec15[l15] = 0.0f; + } + for (int l16 = 0; l16 < 2; l16 = l16 + 1) { + fRec14[l16] = 0.0f; + } + for (int l17 = 0; l17 < 2; l17 = l17 + 1) { + fRec13[l17] = 0.0f; + } + IOTA0 = 0; + for (int l18 = 0; l18 < 512; l18 = l18 + 1) { + fVec5[l18] = 0.0f; + } + for (int l19 = 0; l19 < 3; l19 = l19 + 1) { + fRec12[l19] = 0.0f; + } + for (int l20 = 0; l20 < 2; l20 = l20 + 1) { + fRec7[l20] = 0.0f; + } + for (int l21 = 0; l21 < 2; l21 = l21 + 1) { + fRec29[l21] = 0.0f; + } + for (int l22 = 0; l22 < 3; l22 = l22 + 1) { + fRec30[l22] = 0.0f; + } + for (int l23 = 0; l23 < 2; l23 = l23 + 1) { + fRec4[l23] = 0.0f; + } + for (int l24 = 0; l24 < 2; l24 = l24 + 1) { + fRec34[l24] = 0.0f; + } + for (int l25 = 0; l25 < 512; l25 = l25 + 1) { + fVec6[l25] = 0.0f; + } + for (int l26 = 0; l26 < 3; l26 = l26 + 1) { + fRec35[l26] = 0.0f; + } + for (int l27 = 0; l27 < 2; l27 = l27 + 1) { + fRec31[l27] = 0.0f; + } + for (int l28 = 0; l28 < 2; l28 = l28 + 1) { + fRec36[l28] = 0.0f; + } + for (int l29 = 0; l29 < 3; l29 = l29 + 1) { + fRec37[l29] = 0.0f; + } + for (int l30 = 0; l30 < 2; l30 = l30 + 1) { + fRec5[l30] = 0.0f; + } + for (int l31 = 0; l31 < 2; l31 = l31 + 1) { + fRec38[l31] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual ComplexRain* clone() { + return new ComplexRain(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + FAUSTFLOAT* output1 = outputs[1]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec0[0] = 1; + fRec0[0] = 0.9999f * fRec0[1] + 8.944272e-05f; + iRec3[0] = 1103515245 * iRec3[1] + 12345; + fRec2[0] = 4.656613e-10f * float(iRec3[0]) - fConst9 * (fConst7 * fRec2[2] + fConst5 * fRec2[1]); + float fTemp0 = ComplexRain_faustpower4_f(std::max(0.05f, std::max(0.0f, std::min(1.0f, fConst10 * (fRec2[0] - fRec2[2])))) + -0.05f); + fVec1[0] = fTemp0; + fRec1[0] = fConst12 * (fConst11 * (fTemp0 - fVec1[1]) - fConst3 * fRec1[1]); + int iTemp1 = 1 - iVec0[1]; + float fTemp2 = ((iTemp1) ? 0.0f : fConst13 + fRec11[1]); + fRec11[0] = fTemp2 - std::floor(fTemp2); + int iTemp3 = 1103515245 * (iRec19[1] + 12345); + int iTemp4 = 1103515245 * (iTemp3 + 12345); + int iTemp5 = 1103515245 * (iTemp4 + 12345); + int iTemp6 = 1103515245 * (iTemp5 + 12345); + int iTemp7 = 1103515245 * (iTemp6 + 12345); + int iTemp8 = 1103515245 * (iTemp7 + 12345); + int iTemp9 = 1103515245 * (iTemp8 + 12345); + int iTemp10 = 1103515245 * (iTemp9 + 12345); + int iTemp11 = 1103515245 * (iTemp10 + 12345); + iRec19[0] = 1103515245 * (iTemp11 + 12345); + int iRec20 = iTemp11; + int iRec21 = iTemp10; + int iRec22 = iTemp9; + int iRec23 = iTemp8; + int iRec24 = iTemp7; + int iRec25 = iTemp6; + int iRec26 = iTemp5; + int iRec27 = iTemp4; + int iRec28 = iTemp3; + fRec18[0] = 2.550532e-10f * (float(iRec28) + float(iRec27) + float(iRec26) + float(iRec25) + float(iRec24) + float(iRec23) + float(iRec22) + float(iRec21) + float(iRec20) + float(iRec19[0])) - fConst28 * (fConst26 * fRec18[2] + fConst24 * fRec18[1]); + float fTemp12 = fRec18[0] - fRec18[2]; + fVec3[0] = fTemp12; + fRec17[0] = fConst30 * (fConst29 * (fTemp12 + fVec3[1]) - fConst22 * fRec17[1]); + float fTemp13 = ((iTemp1) ? 0.0f : fRec16[1] + fConst31 * (8e+01f * fRec17[0] + 4e+01f)); + fRec16[0] = fTemp13 - std::floor(fTemp13); + float fTemp14 = std::max(0.35f, 1e+01f * ComplexRain_faustpower2_f(fRec17[0]) * std::cos(6.2831855f * (fRec16[0] + -0.25f))) + -0.35f; + fVec4[0] = fTemp14; + fRec15[0] = fConst30 * (fConst32 * (fTemp14 - fVec4[1]) - fConst22 * fRec15[1]); + fRec14[0] = -(fConst30 * (fConst22 * fRec14[1] - fConst21 * (fRec15[0] - fRec15[1]))); + fRec13[0] = -(fConst35 * (fConst34 * fRec13[1] - fConst33 * (fRec14[0] - fRec14[1]))); + float fTemp15 = 15.0f * fRec13[0]; + fVec5[IOTA0 & 511] = fRec5[1] + fRec7[1] + fTemp15; + float fTemp16 = 0.61f * fVec5[(IOTA0 - iConst36) & 511]; + fRec12[0] = fTemp16 - fConst19 * (fConst17 * fRec12[2] + fConst15 * fRec12[1]); + fRec7[0] = fConst37 * (fRec12[0] - fRec12[2]) * ftbl0ComplexRainSIG0[std::max(0, std::min(int(65536.0f * fRec11[0]), 65535))]; + float fTemp17 = ((iTemp1) ? 0.0f : fConst38 + fRec29[1]); + fRec29[0] = fTemp17 - std::floor(fTemp17); + fRec30[0] = fTemp16 - fConst44 * (fConst42 * fRec30[2] + fConst40 * fRec30[1]); + float fRec8 = fConst45 * (fRec30[0] - fRec30[2]) * ftbl0ComplexRainSIG0[std::max(0, std::min(int(65536.0f * fRec29[0]), 65535))]; + float fRec9 = fTemp16; + fRec4[0] = fRec8; + float fTemp18 = ((iTemp1) ? 0.0f : fConst46 + fRec34[1]); + fRec34[0] = fTemp18 - std::floor(fTemp18); + fVec6[IOTA0 & 511] = fRec4[1] + fTemp15 + fRec31[1]; + float fTemp19 = 0.61f * fVec6[(IOTA0 - iConst53) & 511]; + fRec35[0] = fTemp19 - fConst52 * (fConst50 * fRec35[2] + fConst48 * fRec35[1]); + fRec31[0] = fConst54 * (fRec35[0] - fRec35[2]) * ftbl0ComplexRainSIG0[std::max(0, std::min(int(65536.0f * fRec34[0]), 65535))]; + float fTemp20 = ((iTemp1) ? 0.0f : fConst55 + fRec36[1]); + fRec36[0] = fTemp20 - std::floor(fTemp20); + fRec37[0] = fTemp19 - fConst61 * (fConst59 * fRec37[2] + fConst57 * fRec37[1]); + float fRec32 = fConst62 * (fRec37[0] - fRec37[2]) * ftbl0ComplexRainSIG0[std::max(0, std::min(int(65536.0f * fRec36[0]), 65535))]; + float fRec33 = fTemp19; + fRec5[0] = fRec32; + float fRec6 = fRec9 + fRec33; + float fTemp21 = fRec6 + fRec1[0]; + output0[i0] = FAUSTFLOAT(fTemp21 * fRec0[0]); + fRec38[0] = 0.9999f * fRec38[1] + 4.472136e-05f; + output1[i0] = FAUSTFLOAT(fTemp21 * fRec38[0]); + iVec0[1] = iVec0[0]; + fRec0[1] = fRec0[0]; + iRec3[1] = iRec3[0]; + fRec2[2] = fRec2[1]; + fRec2[1] = fRec2[0]; + fVec1[1] = fVec1[0]; + fRec1[1] = fRec1[0]; + fRec11[1] = fRec11[0]; + iRec19[1] = iRec19[0]; + fRec18[2] = fRec18[1]; + fRec18[1] = fRec18[0]; + fVec3[1] = fVec3[0]; + fRec17[1] = fRec17[0]; + fRec16[1] = fRec16[0]; + fVec4[1] = fVec4[0]; + fRec15[1] = fRec15[0]; + fRec14[1] = fRec14[0]; + fRec13[1] = fRec13[0]; + IOTA0 = IOTA0 + 1; + fRec12[2] = fRec12[1]; + fRec12[1] = fRec12[0]; + fRec7[1] = fRec7[0]; + fRec29[1] = fRec29[0]; + fRec30[2] = fRec30[1]; + fRec30[1] = fRec30[0]; + fRec4[1] = fRec4[0]; + fRec34[1] = fRec34[0]; + fRec35[2] = fRec35[1]; + fRec35[1] = fRec35[0]; + fRec31[1] = fRec31[0]; + fRec36[1] = fRec36[0]; + fRec37[2] = fRec37[1]; + fRec37[1] = fRec37[0]; + fRec5[1] = fRec5[0]; + fRec38[1] = fRec38[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/fmSynthAnalog.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/fmSynthAnalog.cpp new file mode 100644 index 0000000000..a4c866a1fd --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/fmSynthAnalog.cpp @@ -0,0 +1,344 @@ +/* ------------------------------------------------------------ +name: "untitled" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __FMSynthAnalog_H__ +#define __FMSynthAnalog_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS FMSynthAnalog +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +class FMSynthAnalogSIG0 { + + private: + + int iVec0[2]; + int iRec0[2]; + + public: + + int getNumInputsFMSynthAnalogSIG0() { + return 0; + } + int getNumOutputsFMSynthAnalogSIG0() { + return 1; + } + + void instanceInitFMSynthAnalogSIG0(int sample_rate) { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + iRec0[l1] = 0; + } + } + + void fillFMSynthAnalogSIG0(int count, float* table) { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iVec0[0] = 1; + iRec0[0] = (iVec0[1] + iRec0[1]) % 65536; + table[i1] = std::sin(9.58738e-05f * float(iRec0[0])); + iVec0[1] = iVec0[0]; + iRec0[1] = iRec0[0]; + } + } + +}; + +static FMSynthAnalogSIG0* newFMSynthAnalogSIG0() { return (FMSynthAnalogSIG0*)new FMSynthAnalogSIG0(); } +static void deleteFMSynthAnalogSIG0(FMSynthAnalogSIG0* dsp) { delete dsp; } + +static float ftbl0FMSynthAnalogSIG0[65537]; + +class FMSynthAnalog : public dsp { + + private: + + int iVec1[2]; + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + FAUSTFLOAT fHslider0; + float fRec4[2]; + FAUSTFLOAT fHslider1; + FAUSTFLOAT fEntry0; + FAUSTFLOAT fHslider2; + float fRec5[2]; + float fConst3; + float fRec3[2]; + float fRec2[2]; + FAUSTFLOAT fHslider3; + int iRec7[2]; + FAUSTFLOAT fHslider4; + FAUSTFLOAT fHslider5; + float fRec6[2]; + FAUSTFLOAT fEntry1; + float fRec1[2]; + + public: + FMSynthAnalog() { + } + + void metadata(Meta* m) { + m->declare("aanl.lib/name", "Faust Antialiased Nonlinearities"); + m->declare("aanl.lib/version", "1.4.1"); + m->declare("analyzers.lib/name", "Faust Analyzer Library"); + m->declare("analyzers.lib/version", "1.2.0"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("compressors.lib/name", "Faust Compressor Effect Library"); + m->declare("compressors.lib/version", "1.6.0"); + m->declare("delays.lib/name", "Faust Delay Library"); + m->declare("delays.lib/version", "1.1.0"); + m->declare("demos.lib/name", "Faust Demos Library"); + m->declare("demos.lib/version", "1.2.0"); + m->declare("dx7.lib/version", "1.1.0"); + m->declare("envelopes.lib/adsre:author", "Julius O. Smith III"); + m->declare("envelopes.lib/adsre:licence", "STK-4.3"); + m->declare("envelopes.lib/author", "GRAME"); + m->declare("envelopes.lib/copyright", "GRAME"); + m->declare("envelopes.lib/license", "LGPL with exception"); + m->declare("envelopes.lib/name", "Faust Envelope Library"); + m->declare("envelopes.lib/version", "1.3.0"); + m->declare("fds.lib/author", "Romain Michon"); + m->declare("fds.lib/name", "Faust Finite Difference Schemes Library"); + m->declare("fds.lib/version", "1.1.0"); + m->declare("filename", "untitled.dsp"); + m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license"); + m->declare("filters.lib/name", "Faust Filters Library"); + m->declare("filters.lib/version", "1.7.1"); + m->declare("hoa.lib/author", "Pierre Guillot"); + m->declare("hoa.lib/copyright", "2012-2013 Guillot, Paris, Colafrancesco, CICM labex art H2H, U. Paris 8, 2019 Wargreen, 2022 Bonardi, Goutmann"); + m->declare("hoa.lib/name", "High Order Ambisonics library"); + m->declare("hoa.lib/version", "1.4.0"); + m->declare("interpolators.lib/name", "Faust Interpolator Library"); + m->declare("interpolators.lib/version", "1.4.0"); + m->declare("linearalgebra.lib/name", "Faust Linear Algebra Library"); + m->declare("linearalgebra.lib/version", "0.1.0"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("mi.lib/author", "Romain Michon"); + m->declare("mi.lib/copyright", "2018-2020 GRAME / GIPSA-Lab"); + m->declare("mi.lib/name", "Faust mass-interaction physical modelling library"); + m->declare("mi.lib/version", "1.1.0"); + m->declare("misceffects.lib/name", "Misc Effects Library"); + m->declare("misceffects.lib/version", "2.5.1"); + m->declare("name", "untitled"); + m->declare("noises.lib/name", "Faust Noise Generator Library"); + m->declare("noises.lib/version", "1.4.1"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/version", "1.6.0"); + m->declare("phaflangers.lib/name", "Faust Phaser and Flanger Library"); + m->declare("phaflangers.lib/version", "1.1.0"); + m->declare("physmodels.lib/name", "Faust Physical Models Library"); + m->declare("physmodels.lib/version", "1.2.0"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("quantizers.lib/name", "Faust Frequency Quantization Library"); + m->declare("quantizers.lib/version", "1.1.1"); + m->declare("reducemaps.lib/author", "Yann Orlarey"); + m->declare("reducemaps.lib/copyright", "Grame and Yann Orlarey"); + m->declare("reducemaps.lib/license", "LGPL with exception"); + m->declare("reducemaps.lib/name", "Reduce Library"); + m->declare("reducemaps.lib/version", "1.2.0"); + m->declare("reverbs.lib/name", "Faust Reverb Library"); + m->declare("reverbs.lib/version", "1.4.0"); + m->declare("routes.lib/name", "Faust Signal Routing Library"); + m->declare("routes.lib/version", "1.2.0"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "1.6.0"); + m->declare("soundfiles.lib/name", "Faust Soundfile Library"); + m->declare("soundfiles.lib/version", "1.7.0"); + m->declare("spats.lib/name", "Faust Spatialization Library"); + m->declare("spats.lib/version", "1.2.0"); + m->declare("synths.lib/name", "Faust Synthesizer Library"); + m->declare("synths.lib/version", "1.1.0"); + m->declare("vaeffects.lib/name", "Faust Virtual Analog Filter Effect Library"); + m->declare("vaeffects.lib/version", "1.3.0"); + m->declare("wdmodels.lib/name", "Faust Wave Digital Model Library"); + m->declare("wdmodels.lib/version", "1.2.1"); + m->declare("webaudio.lib/author", "GRAME"); + m->declare("webaudio.lib/copyright", "GRAME"); + m->declare("webaudio.lib/license", "LGPL with exception"); + m->declare("webaudio.lib/name", "Faust WebAudio Filters Library"); + m->declare("webaudio.lib/version", "1.1.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 1; + } + + static void classInit(int sample_rate) { + FMSynthAnalogSIG0* sig0 = newFMSynthAnalogSIG0(); + sig0->instanceInitFMSynthAnalogSIG0(sample_rate); + sig0->fillFMSynthAnalogSIG0(65537, ftbl0FMSynthAnalogSIG0); + deleteFMSynthAnalogSIG0(sig0); + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = 44.1f / fConst0; + fConst2 = 1.0f - fConst1; + fConst3 = 1.0f / fConst0; + } + + virtual void instanceResetUserInterface() { + fHslider0 = FAUSTFLOAT(2.0f); + fHslider1 = FAUSTFLOAT(0.0f); + fEntry0 = FAUSTFLOAT(4.4e+02f); + fHslider2 = FAUSTFLOAT(0.0f); + fHslider3 = FAUSTFLOAT(0.01f); + fHslider4 = FAUSTFLOAT(0.6f); + fHslider5 = FAUSTFLOAT(0.2f); + fEntry1 = FAUSTFLOAT(1.0f); + } + + virtual void instanceClear() { + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + iVec1[l2] = 0; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec4[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + fRec5[l4] = 0.0f; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + fRec3[l5] = 0.0f; + } + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + fRec2[l6] = 0.0f; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + iRec7[l7] = 0; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec6[l8] = 0.0f; + } + for (int l9 = 0; l9 < 2; l9 = l9 + 1) { + fRec1[l9] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual FMSynthAnalog* clone() { + return new FMSynthAnalog(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->declare(&fHslider3, "BELA", "ANALOG_1"); + ui_interface->addHorizontalSlider("A", &fHslider3, FAUSTFLOAT(0.01f), FAUSTFLOAT(0.01f), FAUSTFLOAT(4.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider4, "BELA", "ANALOG_2"); + ui_interface->addHorizontalSlider("DR", &fHslider4, FAUSTFLOAT(0.6f), FAUSTFLOAT(0.01f), FAUSTFLOAT(8.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider5, "BELA", "ANALOG_3"); + ui_interface->addHorizontalSlider("S", &fHslider5, FAUSTFLOAT(0.2f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider1, "midi", "pitchwheel"); + ui_interface->addHorizontalSlider("bend", &fHslider1, FAUSTFLOAT(0.0f), FAUSTFLOAT(-2.0f), FAUSTFLOAT(2.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider2, "midi", "ctrl 1"); + ui_interface->addHorizontalSlider("feedb", &fHslider2, FAUSTFLOAT(0.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.001f)); + ui_interface->declare(&fEntry0, "unit", "Hz"); + ui_interface->addNumEntry("freq", &fEntry0, FAUSTFLOAT(4.4e+02f), FAUSTFLOAT(2e+01f), FAUSTFLOAT(2e+04f), FAUSTFLOAT(1.0f)); + ui_interface->addNumEntry("gain", &fEntry1, FAUSTFLOAT(1.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider0, "BELA", "ANALOG_0"); + ui_interface->addHorizontalSlider("ratio", &fHslider0, FAUSTFLOAT(2.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(2e+01f), FAUSTFLOAT(0.01f)); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = fConst1 * float(fHslider0); + float fSlow1 = float(fEntry0) * std::pow(2.0f, 0.083333336f * float(fHslider1)); + float fSlow2 = fConst1 * float(fHslider2); + float fSlow3 = fSlow1 + -1.0f; + float fSlow4 = float(fHslider3); + int iSlow5 = int(fConst0 * fSlow4); + float fSlow6 = float(fHslider4); + float fSlow7 = float(fHslider5); + float fSlow8 = 1e+03f * float(fEntry1); + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec1[0] = 1; + int iTemp0 = 1 - iVec1[1]; + fRec4[0] = fSlow0 + fConst2 * fRec4[1]; + fRec5[0] = fSlow2 + fConst2 * fRec5[1]; + float fTemp1 = ((iTemp0) ? 0.0f : fRec3[1] + fConst3 * (fSlow3 * fRec5[0] * fRec2[1] + fSlow1 * fRec4[0])); + fRec3[0] = fTemp1 - std::floor(fTemp1); + float fTemp2 = 65536.0f * fRec3[0]; + int iTemp3 = int(fTemp2); + float fTemp4 = ftbl0FMSynthAnalogSIG0[std::max(0, std::min(iTemp3, 65536))]; + fRec2[0] = fTemp4 + (fTemp2 - std::floor(fTemp2)) * (ftbl0FMSynthAnalogSIG0[std::max(0, std::min(iTemp3 + 1, 65536))] - fTemp4); + iRec7[0] = iRec7[1] + 1; + int iTemp5 = (iRec7[0] < iSlow5) | (iTemp0 * (iTemp0 > 0)); + float fTemp6 = 0.1447178f * ((iTemp5) ? fSlow4 : fSlow6); + int iTemp7 = std::fabs(fTemp6) < 1.1920929e-07f; + float fTemp8 = ((iTemp7) ? 0.0f : std::exp(-(fConst3 / ((iTemp7) ? 1.0f : fTemp6)))); + fRec6[0] = (1.0f - fTemp8) * ((iTemp5) ? 1.0f : fSlow7) + fTemp8 * fRec6[1]; + float fTemp9 = ((iTemp0) ? 0.0f : fRec1[1] + fConst3 * (fSlow1 + fSlow8 * fRec6[0] * fRec2[0])); + fRec1[0] = fTemp9 - std::floor(fTemp9); + float fTemp10 = 65536.0f * fRec1[0]; + int iTemp11 = int(fTemp10); + float fTemp12 = ftbl0FMSynthAnalogSIG0[std::max(0, std::min(iTemp11, 65536))]; + output0[i0] = FAUSTFLOAT(fRec6[0] * (fTemp12 + (fTemp10 - std::floor(fTemp10)) * (ftbl0FMSynthAnalogSIG0[std::max(0, std::min(iTemp11 + 1, 65536))] - fTemp12))); + iVec1[1] = iVec1[0]; + fRec4[1] = fRec4[0]; + fRec5[1] = fRec5[0]; + fRec3[1] = fRec3[0]; + fRec2[1] = fRec2[0]; + iRec7[1] = iRec7[0]; + fRec6[1] = fRec6[0]; + fRec1[1] = fRec1[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/insects.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/insects.cpp new file mode 100644 index 0000000000..5dcb58302a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/insects.cpp @@ -0,0 +1,1410 @@ +/* ------------------------------------------------------------ +name: "untitled" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __Insects_H__ +#define __Insects_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS Insects +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +class InsectsSIG0 { + + private: + + int iVec1[2]; + int iRec10[2]; + + public: + + int getNumInputsInsectsSIG0() { + return 0; + } + int getNumOutputsInsectsSIG0() { + return 1; + } + + void instanceInitInsectsSIG0(int sample_rate) { + for (int l11 = 0; l11 < 2; l11 = l11 + 1) { + iVec1[l11] = 0; + } + for (int l12 = 0; l12 < 2; l12 = l12 + 1) { + iRec10[l12] = 0; + } + } + + void fillInsectsSIG0(int count, float* table) { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iVec1[0] = 1; + iRec10[0] = (iVec1[1] + iRec10[1]) % 65536; + table[i1] = std::sin(9.58738e-05f * float(iRec10[0])); + iVec1[1] = iVec1[0]; + iRec10[1] = iRec10[0]; + } + } + +}; + +static InsectsSIG0* newInsectsSIG0() { return (InsectsSIG0*)new InsectsSIG0(); } +static void deleteInsectsSIG0(InsectsSIG0* dsp) { delete dsp; } + +static float Insects_faustpower2_f(float value) { + return value * value; +} +static float ftbl0InsectsSIG0[65536]; + +class Insects : public dsp { + + private: + + int iVec0[2]; + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + float fConst3; + float fConst4; + float fConst5; + float fConst6; + float fRec1[2]; + float fConst7; + float fRec2[2]; + float fConst8; + float fRec3[2]; + float fConst9; + float fRec4[2]; + float fRec0[3]; + float fConst10; + float fRec6[2]; + float fConst11; + float fRec7[2]; + float fConst12; + float fRec8[2]; + float fConst13; + float fRec9[2]; + float fRec5[3]; + float fConst14; + float fRec11[2]; + float fConst15; + float fConst16; + float fConst17; + float fConst18; + float fConst19; + int iRec13[2]; + float fVec2[2]; + float fRec12[3]; + float fConst20; + float fConst21; + float fConst22; + float fConst23; + float fConst24; + float fConst25; + float fRec18[2]; + float fVec3[2]; + float fRec17[2]; + float fRec16[2]; + float fConst26; + float fRec15[2]; + float fRec14[3]; + float fConst27; + float fConst28; + float fConst29; + float fConst30; + float fConst31; + float fConst32; + float fConst33; + float fConst34; + float fConst35; + float fConst36; + int iConst37; + int iRec22[2]; + float fConst38; + float fRec25[2]; + float fVec4[2]; + float fRec24[2]; + float fConst39; + float fRec23[2]; + int iVec5[2]; + int iRec21[2]; + float fConst40; + int iRec26[2]; + float fConst41; + float fRec27[3]; + float fRec20[3]; + float fRec29[3]; + float fRec28[3]; + float fRec31[3]; + float fRec30[3]; + float fRec19[3]; + int iRec34[2]; + float fRec33[2]; + float fRec48[2]; + float fRec32[2]; + int iConst42; + int iRec52[2]; + float fConst43; + float fRec55[2]; + float fVec6[2]; + float fRec54[2]; + float fConst44; + float fRec53[2]; + int iVec7[2]; + int iRec51[2]; + float fConst45; + int iRec56[2]; + float fRec57[3]; + float fRec50[3]; + float fRec59[3]; + float fRec58[3]; + float fRec61[3]; + float fRec60[3]; + float fRec49[3]; + float fRec63[2]; + float fRec64[2]; + float fRec62[2]; + float fConst46; + int iConst47; + int iRec68[2]; + float fConst48; + float fRec71[2]; + float fVec8[2]; + float fRec70[2]; + float fRec69[2]; + int iVec9[2]; + int iRec67[2]; + float fConst49; + int iRec72[2]; + float fRec73[3]; + float fRec66[3]; + float fRec75[3]; + float fRec74[3]; + float fRec77[3]; + float fRec76[3]; + float fRec65[3]; + float fRec79[2]; + float fRec80[2]; + float fRec78[2]; + float fConst50; + float fRec81[2]; + float fConst51; + float fRec82[2]; + int iConst52; + int iRec84[2]; + float fConst53; + float fRec87[2]; + float fVec10[2]; + float fRec86[2]; + float fConst54; + float fRec85[2]; + float fConst55; + float fRec88[2]; + float fRec83[2]; + float fConst56; + float fRec89[2]; + float fRec91[2]; + float fRec92[2]; + float fRec90[2]; + float fConst57; + float fRec93[2]; + float fConst58; + float fRec94[2]; + float fConst59; + float fRec98[2]; + float fVec11[2]; + float fRec97[2]; + float fConst60; + float fRec96[2]; + float fRec95[2]; + float fRec99[2]; + float fRec101[2]; + float fRec102[2]; + float fRec100[2]; + float fConst61; + float fRec103[2]; + float fConst62; + float fRec104[2]; + float fConst63; + float fRec108[2]; + float fVec12[2]; + float fRec107[2]; + float fConst64; + float fRec106[2]; + float fRec105[2]; + float fRec109[2]; + float fRec111[2]; + float fRec112[2]; + float fRec110[2]; + float fConst65; + float fRec113[2]; + float fConst66; + float fRec114[2]; + int iConst67; + int iRec116[2]; + float fConst68; + float fRec119[2]; + float fVec13[2]; + float fRec118[2]; + float fConst69; + float fRec117[2]; + float fRec115[2]; + float fRec120[2]; + float fRec122[2]; + float fRec123[2]; + float fRec121[2]; + float fConst70; + float fConst71; + float fConst72; + float fRec130[2]; + float fRec131[2]; + float fRec129[2]; + float fConst73; + float fConst74; + float fConst75; + float fRec128[2]; + float fRec127[2]; + float fRec126[2]; + float fRec125[2]; + float fRec124[2]; + float fRec132[2]; + float fRec133[2]; + float fRec134[2]; + float fRec135[2]; + float fRec136[2]; + float fRec137[2]; + float fRec138[2]; + + public: + Insects() { + } + + void metadata(Meta* m) { + m->declare("aanl.lib/name", "Faust Antialiased Nonlinearities"); + m->declare("aanl.lib/version", "1.4.1"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/sAndH:author", "Romain Michon"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("envelopes.lib/asr:author", "Yann Orlarey, Stéphane Letz"); + m->declare("envelopes.lib/author", "GRAME"); + m->declare("envelopes.lib/copyright", "GRAME"); + m->declare("envelopes.lib/license", "LGPL with exception"); + m->declare("envelopes.lib/name", "Faust Envelope Library"); + m->declare("envelopes.lib/version", "1.3.0"); + m->declare("filename", "untitled.dsp"); + m->declare("filters.lib/fir:author", "Julius O. Smith III"); + m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/iir:author", "Julius O. Smith III"); + m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/lowpass0_highpass1", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III"); + m->declare("filters.lib/lowpass:author", "Julius O. Smith III"); + m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/name", "Faust Filters Library"); + m->declare("filters.lib/nlf2:author", "Julius O. Smith III"); + m->declare("filters.lib/nlf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/nlf2:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/resonbp:author", "Julius O. Smith III"); + m->declare("filters.lib/resonbp:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/resonbp:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/resonhp:author", "Julius O. Smith III"); + m->declare("filters.lib/resonhp:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/resonhp:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/resonlp:author", "Julius O. Smith III"); + m->declare("filters.lib/resonlp:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/resonlp:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf1:author", "Julius O. Smith III"); + m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf1s:author", "Julius O. Smith III"); + m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf2:author", "Julius O. Smith III"); + m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/tf2s:author", "Julius O. Smith III"); + m->declare("filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf2s:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/version", "1.7.1"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("noises.lib/name", "Faust Noise Generator Library"); + m->declare("noises.lib/version", "1.4.1"); + m->declare("oscillators.lib/lf_sawpos:author", "Bart Brouns, revised by Stéphane Letz"); + m->declare("oscillators.lib/lf_sawpos:licence", "STK-4.3"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/version", "1.6.0"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("routes.lib/name", "Faust Signal Routing Library"); + m->declare("routes.lib/version", "1.2.0"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "1.6.0"); + m->declare("spats.lib/name", "Faust Spatialization Library"); + m->declare("spats.lib/spat:author", "Laurent Pottier, revised by Romain Michon"); + m->declare("spats.lib/version", "1.2.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 2; + } + + static void classInit(int sample_rate) { + InsectsSIG0* sig0 = newInsectsSIG0(); + sig0->instanceInitInsectsSIG0(sample_rate); + sig0->fillInsectsSIG0(65536, ftbl0InsectsSIG0); + deleteInsectsSIG0(sig0); + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = std::tan(62.831852f / fConst0); + fConst2 = 2.0f * (1.0f - 1.0f / Insects_faustpower2_f(fConst1)); + fConst3 = 1.0f / fConst1; + fConst4 = 1.0f - (1.0f - fConst3) / fConst1; + fConst5 = 1.0f / ((fConst3 + 1.0f) / fConst1 + 1.0f); + fConst6 = 15.5f / fConst0; + fConst7 = 20.4f / fConst0; + fConst8 = 4.279f / fConst0; + fConst9 = 2134.0f / fConst0; + fConst10 = 2.0f / fConst0; + fConst11 = 2e+01f / fConst0; + fConst12 = 4.0f / fConst0; + fConst13 = 2012.0f / fConst0; + fConst14 = 0.01f / fConst0; + fConst15 = std::tan(2513.2742f / fConst0); + fConst16 = 2.0f * (1.0f - 1.0f / Insects_faustpower2_f(fConst15)); + fConst17 = 1.0f / fConst15; + fConst18 = 1.0f - (1.0f - fConst17) / fConst15; + fConst19 = 1.0f / ((fConst17 + 1.0f) / fConst15 + 1.0f); + fConst20 = std::tan(2670.3538f / fConst0); + fConst21 = 2.0f * (1.0f - 1.0f / Insects_faustpower2_f(fConst20)); + fConst22 = 1.0f / fConst20; + fConst23 = (fConst22 + -0.06666667f) / fConst20 + 1.0f; + fConst24 = 1.0f / ((fConst22 + 0.06666667f) / fConst20 + 1.0f); + fConst25 = 2.5e+02f / fConst0; + fConst26 = 1.0f / fConst0; + fConst27 = std::tan(31.415926f / fConst0); + fConst28 = 2.0f * (1.0f - 1.0f / Insects_faustpower2_f(fConst27)); + fConst29 = 1.0f / fConst27; + fConst30 = 1.0f - (1.0f - fConst29) / fConst27; + fConst31 = 1.0f / ((fConst29 + 1.0f) / fConst27 + 1.0f); + fConst32 = std::tan(4398.2295f / fConst0); + fConst33 = 2.0f * (1.0f - 1.0f / Insects_faustpower2_f(fConst32)); + fConst34 = 1.0f / fConst32; + fConst35 = 1.0f - (1.0f - fConst34) / fConst32; + fConst36 = 1.0f / ((fConst34 + 1.0f) / fConst32 + 1.0f); + iConst37 = int(0.15f * fConst0); + fConst38 = 0.087f / fConst0; + fConst39 = 0.75f * fConst0; + fConst40 = 1.0f / std::max(1.0f, 0.2f * fConst0); + fConst41 = 3.1415927f / fConst0; + iConst42 = int(0.3f * fConst0); + fConst43 = 0.09f / fConst0; + fConst44 = 0.6f * fConst0; + fConst45 = 1.0f / std::max(1.0f, 0.4f * fConst0); + fConst46 = 0.25f * fConst0; + iConst47 = int(fConst46); + fConst48 = 0.093f / fConst0; + fConst49 = 1.0f / std::max(1.0f, fConst46); + fConst50 = 1842.0f / fConst0; + fConst51 = 6134.0f / fConst0; + iConst52 = int(0.32f * fConst0); + fConst53 = 0.0921f / fConst0; + fConst54 = 1.28f * fConst0; + fConst55 = 0.8f / fConst0; + fConst56 = 1.25f * fConst0; + fConst57 = 15342.0f / fConst0; + fConst58 = 8134.0f / fConst0; + fConst59 = 0.05f / fConst0; + fConst60 = 1.5f * fConst0; + fConst61 = 8342.0f / fConst0; + fConst62 = 3134.0f / fConst0; + fConst63 = 0.15f / fConst0; + fConst64 = 0.9f * fConst0; + fConst65 = 12342.0f / fConst0; + fConst66 = 5134.0f / fConst0; + iConst67 = int(0.5f * fConst0); + fConst68 = 0.1f / fConst0; + fConst69 = 2.5f * fConst0; + fConst70 = 3141.5928f / fConst0; + fConst71 = std::cos(fConst70); + fConst72 = std::sin(fConst70); + fConst73 = 1.0f / std::tan(1570.7964f / fConst0); + fConst74 = 1.0f - fConst73; + fConst75 = 1.0f / (fConst73 + 1.0f); + } + + virtual void instanceResetUserInterface() { + } + + virtual void instanceClear() { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + fRec1[l1] = 0.0f; + } + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + fRec2[l2] = 0.0f; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec3[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + fRec4[l4] = 0.0f; + } + for (int l5 = 0; l5 < 3; l5 = l5 + 1) { + fRec0[l5] = 0.0f; + } + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + fRec6[l6] = 0.0f; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + fRec7[l7] = 0.0f; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec8[l8] = 0.0f; + } + for (int l9 = 0; l9 < 2; l9 = l9 + 1) { + fRec9[l9] = 0.0f; + } + for (int l10 = 0; l10 < 3; l10 = l10 + 1) { + fRec5[l10] = 0.0f; + } + for (int l13 = 0; l13 < 2; l13 = l13 + 1) { + fRec11[l13] = 0.0f; + } + for (int l14 = 0; l14 < 2; l14 = l14 + 1) { + iRec13[l14] = 0; + } + for (int l15 = 0; l15 < 2; l15 = l15 + 1) { + fVec2[l15] = 0.0f; + } + for (int l16 = 0; l16 < 3; l16 = l16 + 1) { + fRec12[l16] = 0.0f; + } + for (int l17 = 0; l17 < 2; l17 = l17 + 1) { + fRec18[l17] = 0.0f; + } + for (int l18 = 0; l18 < 2; l18 = l18 + 1) { + fVec3[l18] = 0.0f; + } + for (int l19 = 0; l19 < 2; l19 = l19 + 1) { + fRec17[l19] = 0.0f; + } + for (int l20 = 0; l20 < 2; l20 = l20 + 1) { + fRec16[l20] = 0.0f; + } + for (int l21 = 0; l21 < 2; l21 = l21 + 1) { + fRec15[l21] = 0.0f; + } + for (int l22 = 0; l22 < 3; l22 = l22 + 1) { + fRec14[l22] = 0.0f; + } + for (int l23 = 0; l23 < 2; l23 = l23 + 1) { + iRec22[l23] = 0; + } + for (int l24 = 0; l24 < 2; l24 = l24 + 1) { + fRec25[l24] = 0.0f; + } + for (int l25 = 0; l25 < 2; l25 = l25 + 1) { + fVec4[l25] = 0.0f; + } + for (int l26 = 0; l26 < 2; l26 = l26 + 1) { + fRec24[l26] = 0.0f; + } + for (int l27 = 0; l27 < 2; l27 = l27 + 1) { + fRec23[l27] = 0.0f; + } + for (int l28 = 0; l28 < 2; l28 = l28 + 1) { + iVec5[l28] = 0; + } + for (int l29 = 0; l29 < 2; l29 = l29 + 1) { + iRec21[l29] = 0; + } + for (int l30 = 0; l30 < 2; l30 = l30 + 1) { + iRec26[l30] = 0; + } + for (int l31 = 0; l31 < 3; l31 = l31 + 1) { + fRec27[l31] = 0.0f; + } + for (int l32 = 0; l32 < 3; l32 = l32 + 1) { + fRec20[l32] = 0.0f; + } + for (int l33 = 0; l33 < 3; l33 = l33 + 1) { + fRec29[l33] = 0.0f; + } + for (int l34 = 0; l34 < 3; l34 = l34 + 1) { + fRec28[l34] = 0.0f; + } + for (int l35 = 0; l35 < 3; l35 = l35 + 1) { + fRec31[l35] = 0.0f; + } + for (int l36 = 0; l36 < 3; l36 = l36 + 1) { + fRec30[l36] = 0.0f; + } + for (int l37 = 0; l37 < 3; l37 = l37 + 1) { + fRec19[l37] = 0.0f; + } + for (int l38 = 0; l38 < 2; l38 = l38 + 1) { + iRec34[l38] = 0; + } + for (int l39 = 0; l39 < 2; l39 = l39 + 1) { + fRec33[l39] = 0.0f; + } + for (int l40 = 0; l40 < 2; l40 = l40 + 1) { + fRec48[l40] = 0.0f; + } + for (int l41 = 0; l41 < 2; l41 = l41 + 1) { + fRec32[l41] = 0.0f; + } + for (int l42 = 0; l42 < 2; l42 = l42 + 1) { + iRec52[l42] = 0; + } + for (int l43 = 0; l43 < 2; l43 = l43 + 1) { + fRec55[l43] = 0.0f; + } + for (int l44 = 0; l44 < 2; l44 = l44 + 1) { + fVec6[l44] = 0.0f; + } + for (int l45 = 0; l45 < 2; l45 = l45 + 1) { + fRec54[l45] = 0.0f; + } + for (int l46 = 0; l46 < 2; l46 = l46 + 1) { + fRec53[l46] = 0.0f; + } + for (int l47 = 0; l47 < 2; l47 = l47 + 1) { + iVec7[l47] = 0; + } + for (int l48 = 0; l48 < 2; l48 = l48 + 1) { + iRec51[l48] = 0; + } + for (int l49 = 0; l49 < 2; l49 = l49 + 1) { + iRec56[l49] = 0; + } + for (int l50 = 0; l50 < 3; l50 = l50 + 1) { + fRec57[l50] = 0.0f; + } + for (int l51 = 0; l51 < 3; l51 = l51 + 1) { + fRec50[l51] = 0.0f; + } + for (int l52 = 0; l52 < 3; l52 = l52 + 1) { + fRec59[l52] = 0.0f; + } + for (int l53 = 0; l53 < 3; l53 = l53 + 1) { + fRec58[l53] = 0.0f; + } + for (int l54 = 0; l54 < 3; l54 = l54 + 1) { + fRec61[l54] = 0.0f; + } + for (int l55 = 0; l55 < 3; l55 = l55 + 1) { + fRec60[l55] = 0.0f; + } + for (int l56 = 0; l56 < 3; l56 = l56 + 1) { + fRec49[l56] = 0.0f; + } + for (int l57 = 0; l57 < 2; l57 = l57 + 1) { + fRec63[l57] = 0.0f; + } + for (int l58 = 0; l58 < 2; l58 = l58 + 1) { + fRec64[l58] = 0.0f; + } + for (int l59 = 0; l59 < 2; l59 = l59 + 1) { + fRec62[l59] = 0.0f; + } + for (int l60 = 0; l60 < 2; l60 = l60 + 1) { + iRec68[l60] = 0; + } + for (int l61 = 0; l61 < 2; l61 = l61 + 1) { + fRec71[l61] = 0.0f; + } + for (int l62 = 0; l62 < 2; l62 = l62 + 1) { + fVec8[l62] = 0.0f; + } + for (int l63 = 0; l63 < 2; l63 = l63 + 1) { + fRec70[l63] = 0.0f; + } + for (int l64 = 0; l64 < 2; l64 = l64 + 1) { + fRec69[l64] = 0.0f; + } + for (int l65 = 0; l65 < 2; l65 = l65 + 1) { + iVec9[l65] = 0; + } + for (int l66 = 0; l66 < 2; l66 = l66 + 1) { + iRec67[l66] = 0; + } + for (int l67 = 0; l67 < 2; l67 = l67 + 1) { + iRec72[l67] = 0; + } + for (int l68 = 0; l68 < 3; l68 = l68 + 1) { + fRec73[l68] = 0.0f; + } + for (int l69 = 0; l69 < 3; l69 = l69 + 1) { + fRec66[l69] = 0.0f; + } + for (int l70 = 0; l70 < 3; l70 = l70 + 1) { + fRec75[l70] = 0.0f; + } + for (int l71 = 0; l71 < 3; l71 = l71 + 1) { + fRec74[l71] = 0.0f; + } + for (int l72 = 0; l72 < 3; l72 = l72 + 1) { + fRec77[l72] = 0.0f; + } + for (int l73 = 0; l73 < 3; l73 = l73 + 1) { + fRec76[l73] = 0.0f; + } + for (int l74 = 0; l74 < 3; l74 = l74 + 1) { + fRec65[l74] = 0.0f; + } + for (int l75 = 0; l75 < 2; l75 = l75 + 1) { + fRec79[l75] = 0.0f; + } + for (int l76 = 0; l76 < 2; l76 = l76 + 1) { + fRec80[l76] = 0.0f; + } + for (int l77 = 0; l77 < 2; l77 = l77 + 1) { + fRec78[l77] = 0.0f; + } + for (int l78 = 0; l78 < 2; l78 = l78 + 1) { + fRec81[l78] = 0.0f; + } + for (int l79 = 0; l79 < 2; l79 = l79 + 1) { + fRec82[l79] = 0.0f; + } + for (int l80 = 0; l80 < 2; l80 = l80 + 1) { + iRec84[l80] = 0; + } + for (int l81 = 0; l81 < 2; l81 = l81 + 1) { + fRec87[l81] = 0.0f; + } + for (int l82 = 0; l82 < 2; l82 = l82 + 1) { + fVec10[l82] = 0.0f; + } + for (int l83 = 0; l83 < 2; l83 = l83 + 1) { + fRec86[l83] = 0.0f; + } + for (int l84 = 0; l84 < 2; l84 = l84 + 1) { + fRec85[l84] = 0.0f; + } + for (int l85 = 0; l85 < 2; l85 = l85 + 1) { + fRec88[l85] = 0.0f; + } + for (int l86 = 0; l86 < 2; l86 = l86 + 1) { + fRec83[l86] = 0.0f; + } + for (int l87 = 0; l87 < 2; l87 = l87 + 1) { + fRec89[l87] = 0.0f; + } + for (int l88 = 0; l88 < 2; l88 = l88 + 1) { + fRec91[l88] = 0.0f; + } + for (int l89 = 0; l89 < 2; l89 = l89 + 1) { + fRec92[l89] = 0.0f; + } + for (int l90 = 0; l90 < 2; l90 = l90 + 1) { + fRec90[l90] = 0.0f; + } + for (int l91 = 0; l91 < 2; l91 = l91 + 1) { + fRec93[l91] = 0.0f; + } + for (int l92 = 0; l92 < 2; l92 = l92 + 1) { + fRec94[l92] = 0.0f; + } + for (int l93 = 0; l93 < 2; l93 = l93 + 1) { + fRec98[l93] = 0.0f; + } + for (int l94 = 0; l94 < 2; l94 = l94 + 1) { + fVec11[l94] = 0.0f; + } + for (int l95 = 0; l95 < 2; l95 = l95 + 1) { + fRec97[l95] = 0.0f; + } + for (int l96 = 0; l96 < 2; l96 = l96 + 1) { + fRec96[l96] = 0.0f; + } + for (int l97 = 0; l97 < 2; l97 = l97 + 1) { + fRec95[l97] = 0.0f; + } + for (int l98 = 0; l98 < 2; l98 = l98 + 1) { + fRec99[l98] = 0.0f; + } + for (int l99 = 0; l99 < 2; l99 = l99 + 1) { + fRec101[l99] = 0.0f; + } + for (int l100 = 0; l100 < 2; l100 = l100 + 1) { + fRec102[l100] = 0.0f; + } + for (int l101 = 0; l101 < 2; l101 = l101 + 1) { + fRec100[l101] = 0.0f; + } + for (int l102 = 0; l102 < 2; l102 = l102 + 1) { + fRec103[l102] = 0.0f; + } + for (int l103 = 0; l103 < 2; l103 = l103 + 1) { + fRec104[l103] = 0.0f; + } + for (int l104 = 0; l104 < 2; l104 = l104 + 1) { + fRec108[l104] = 0.0f; + } + for (int l105 = 0; l105 < 2; l105 = l105 + 1) { + fVec12[l105] = 0.0f; + } + for (int l106 = 0; l106 < 2; l106 = l106 + 1) { + fRec107[l106] = 0.0f; + } + for (int l107 = 0; l107 < 2; l107 = l107 + 1) { + fRec106[l107] = 0.0f; + } + for (int l108 = 0; l108 < 2; l108 = l108 + 1) { + fRec105[l108] = 0.0f; + } + for (int l109 = 0; l109 < 2; l109 = l109 + 1) { + fRec109[l109] = 0.0f; + } + for (int l110 = 0; l110 < 2; l110 = l110 + 1) { + fRec111[l110] = 0.0f; + } + for (int l111 = 0; l111 < 2; l111 = l111 + 1) { + fRec112[l111] = 0.0f; + } + for (int l112 = 0; l112 < 2; l112 = l112 + 1) { + fRec110[l112] = 0.0f; + } + for (int l113 = 0; l113 < 2; l113 = l113 + 1) { + fRec113[l113] = 0.0f; + } + for (int l114 = 0; l114 < 2; l114 = l114 + 1) { + fRec114[l114] = 0.0f; + } + for (int l115 = 0; l115 < 2; l115 = l115 + 1) { + iRec116[l115] = 0; + } + for (int l116 = 0; l116 < 2; l116 = l116 + 1) { + fRec119[l116] = 0.0f; + } + for (int l117 = 0; l117 < 2; l117 = l117 + 1) { + fVec13[l117] = 0.0f; + } + for (int l118 = 0; l118 < 2; l118 = l118 + 1) { + fRec118[l118] = 0.0f; + } + for (int l119 = 0; l119 < 2; l119 = l119 + 1) { + fRec117[l119] = 0.0f; + } + for (int l120 = 0; l120 < 2; l120 = l120 + 1) { + fRec115[l120] = 0.0f; + } + for (int l121 = 0; l121 < 2; l121 = l121 + 1) { + fRec120[l121] = 0.0f; + } + for (int l122 = 0; l122 < 2; l122 = l122 + 1) { + fRec122[l122] = 0.0f; + } + for (int l123 = 0; l123 < 2; l123 = l123 + 1) { + fRec123[l123] = 0.0f; + } + for (int l124 = 0; l124 < 2; l124 = l124 + 1) { + fRec121[l124] = 0.0f; + } + for (int l125 = 0; l125 < 2; l125 = l125 + 1) { + fRec130[l125] = 0.0f; + } + for (int l126 = 0; l126 < 2; l126 = l126 + 1) { + fRec131[l126] = 0.0f; + } + for (int l127 = 0; l127 < 2; l127 = l127 + 1) { + fRec129[l127] = 0.0f; + } + for (int l128 = 0; l128 < 2; l128 = l128 + 1) { + fRec128[l128] = 0.0f; + } + for (int l129 = 0; l129 < 2; l129 = l129 + 1) { + fRec127[l129] = 0.0f; + } + for (int l130 = 0; l130 < 2; l130 = l130 + 1) { + fRec126[l130] = 0.0f; + } + for (int l131 = 0; l131 < 2; l131 = l131 + 1) { + fRec125[l131] = 0.0f; + } + for (int l132 = 0; l132 < 2; l132 = l132 + 1) { + fRec124[l132] = 0.0f; + } + for (int l133 = 0; l133 < 2; l133 = l133 + 1) { + fRec132[l133] = 0.0f; + } + for (int l134 = 0; l134 < 2; l134 = l134 + 1) { + fRec133[l134] = 0.0f; + } + for (int l135 = 0; l135 < 2; l135 = l135 + 1) { + fRec134[l135] = 0.0f; + } + for (int l136 = 0; l136 < 2; l136 = l136 + 1) { + fRec135[l136] = 0.0f; + } + for (int l137 = 0; l137 < 2; l137 = l137 + 1) { + fRec136[l137] = 0.0f; + } + for (int l138 = 0; l138 < 2; l138 = l138 + 1) { + fRec137[l138] = 0.0f; + } + for (int l139 = 0; l139 < 2; l139 = l139 + 1) { + fRec138[l139] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual Insects* clone() { + return new Insects(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + FAUSTFLOAT* output1 = outputs[1]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec0[0] = 1; + int iTemp0 = 1 - iVec0[1]; + float fTemp1 = ((iTemp0) ? 0.0f : fConst6 + fRec1[1]); + fRec1[0] = fTemp1 - std::floor(fTemp1); + float fTemp2 = ((iTemp0) ? 0.0f : fConst7 + fRec2[1]); + fRec2[0] = fTemp2 - std::floor(fTemp2); + float fTemp3 = ((iTemp0) ? 0.0f : fConst8 + fRec3[1]); + fRec3[0] = fTemp3 - std::floor(fTemp3); + float fTemp4 = ((iTemp0) ? 0.0f : fConst9 + fRec4[1]); + fRec4[0] = fTemp4 - std::floor(fTemp4); + float fTemp5 = std::cos(6.2831855f * fRec4[0]) * std::cos(6.2831855f * fRec3[0]) * std::cos(6.2831855f * fRec2[0]) * std::cos(6.2831855f * fRec1[0]); + fRec0[0] = fTemp5 - fConst5 * (fConst4 * fRec0[2] + fConst2 * fRec0[1]); + float fTemp6 = ((iTemp0) ? 0.0f : fConst10 + fRec6[1]); + fRec6[0] = fTemp6 - std::floor(fTemp6); + float fTemp7 = ((iTemp0) ? 0.0f : fConst11 + fRec7[1]); + fRec7[0] = fTemp7 - std::floor(fTemp7); + float fTemp8 = ((iTemp0) ? 0.0f : fConst12 + fRec8[1]); + fRec8[0] = fTemp8 - std::floor(fTemp8); + float fTemp9 = ((iTemp0) ? 0.0f : fConst13 + fRec9[1]); + fRec9[0] = fTemp9 - std::floor(fTemp9); + float fTemp10 = std::cos(6.2831855f * fRec9[0]) * std::cos(6.2831855f * fRec8[0]) * std::cos(6.2831855f * fRec7[0]) * std::cos(6.2831855f * fRec6[0]); + fRec5[0] = fTemp10 - fConst5 * (fConst4 * fRec5[2] + fConst2 * fRec5[1]); + float fTemp11 = ((iTemp0) ? 0.0f : fConst14 + fRec11[1]); + fRec11[0] = fTemp11 - std::floor(fTemp11); + iRec13[0] = 1103515245 * iRec13[1] + 12345; + float fTemp12 = float(iRec13[0]); + fVec2[0] = fTemp12; + float fTemp13 = 4.656613e-10f * fTemp12; + fRec12[0] = fTemp13 - fConst19 * (fConst18 * fRec12[2] + fConst16 * fRec12[1]); + float fTemp14 = ((iTemp0) ? 0.0f : fConst25 + fRec18[1]); + fRec18[0] = fTemp14 - std::floor(fTemp14); + float fTemp15 = fRec18[0] - fRec18[1]; + fVec3[0] = fTemp15; + int iTemp16 = (fVec3[1] <= 0.0f) & (fTemp15 > 0.0f); + fRec17[0] = fRec17[1] * float(1 - iTemp16) + 4.656613e-10f * fTemp12 * float(iTemp16); + float fTemp17 = 0.5f * (fRec17[0] + 1.0f); + fRec16[0] = ((std::fabs(4.656613e-10f * fVec2[1] * float((fRec18[0] >= fTemp17) * (fRec18[1] < fTemp17))) > 0.0f) ? std::fabs(fTemp13) : fRec16[1]); + float fTemp18 = ((iTemp0) ? 0.0f : fRec15[1] + fConst26 * (1.2e+03f * fRec16[0] + 4e+02f)); + fRec15[0] = fTemp18 - std::floor(fTemp18); + float fTemp19 = ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec15[0]), 65535))]; + fRec14[0] = fTemp19 - fConst24 * (fConst23 * fRec14[2] + fConst21 * fRec14[1]); + float fTemp20 = 0.4f * (0.008f * (fTemp19 - fConst24 * (fRec14[2] + fRec14[0] + 2.0f * fRec14[1])) + fConst19 * (0.08f * fRec12[0] + 0.16f * fRec12[1] + 0.08f * fRec12[2]) + 0.025f * ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec11[0]), 65535))] * (fTemp10 - fConst5 * (fRec5[2] + fRec5[0] + 2.0f * fRec5[1]) + (fTemp5 - fConst5 * (fRec0[2] + fRec0[0] + 2.0f * fRec0[1])))); + iRec22[0] = (iVec0[1] + iRec22[1]) % iConst37; + float fTemp21 = ((iTemp0) ? 0.0f : fConst38 + fRec25[1]); + fRec25[0] = fTemp21 - std::floor(fTemp21); + float fTemp22 = fRec25[0] - fRec25[1]; + fVec4[0] = fTemp22; + int iTemp23 = (fVec4[1] <= 0.0f) & (fTemp22 > 0.0f); + fRec24[0] = fRec24[1] * float(1 - iTemp23) + 4.656613e-10f * fTemp12 * float(iTemp23); + float fTemp24 = 0.5f * (fRec24[0] + 1.0f); + int iTemp25 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec25[0] >= fTemp24) * (fRec25[1] < fTemp24))) > 0.0f; + fRec23[0] = ((iTemp25 > 0) ? fConst39 : std::max(0.0f, fRec23[1] + -1.0f)); + int iTemp26 = (fRec23[0] > 0.0f) * (iRec22[0] <= iRec22[1]); + iVec5[0] = iTemp26; + iRec21[0] = (iRec21[1] + 1) * (iTemp26 == 0); + iRec26[0] = iTemp26 + iRec26[1] * (iVec5[1] >= iTemp26); + float fTemp27 = std::max(0.0f, std::min(float(iRec26[0]), 1.0f) - fConst40 * float(iRec21[0])); + float fTemp28 = 1.0f - fTemp27; + float fTemp29 = std::min(0.5f, fTemp28) - std::max(0.9f, fTemp28); + float fTemp30 = std::tan(fConst41 * (7.2e+02f * fTemp29 + 2.4e+03f)); + float fTemp31 = 1.0f / fTemp30; + float fTemp32 = (fTemp31 + 0.33333334f) / fTemp30 + 1.0f; + float fTemp33 = 18.0f * Insects_faustpower2_f(std::min(0.5f, fTemp27) - std::max(0.5f, fTemp27)); + float fTemp34 = 1.0f / (14884.0f * Insects_faustpower2_f(fTemp33 + (-1.0f - float(int(fTemp33 + -1.0f)))) + 1.0f); + fRec27[0] = fTemp34 - (fRec27[2] * ((fTemp31 + -0.33333334f) / fTemp30 + 1.0f) + 2.0f * fRec27[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp30))) / fTemp32; + fRec20[0] = (fRec27[0] - fRec27[2]) / (fTemp30 * fTemp32) - fConst36 * (fConst35 * fRec20[2] + fConst33 * fRec20[1]); + float fTemp35 = std::tan(fConst41 * (1.2e+02f * fTemp29 + 8e+02f)); + float fTemp36 = 1.0f / fTemp35; + float fTemp37 = (fTemp36 + 0.2f) / fTemp35 + 1.0f; + fRec29[0] = fTemp34 - (fRec29[2] * ((fTemp36 + -0.2f) / fTemp35 + 1.0f) + 2.0f * fRec29[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp35))) / fTemp37; + fRec28[0] = (fRec29[0] - fRec29[2]) / (fTemp35 * fTemp37) - fConst36 * (fConst35 * fRec28[2] + fConst33 * fRec28[1]); + float fTemp38 = std::tan(fConst41 * (2.7e+02f * fTemp29 + 1.6e+03f)); + float fTemp39 = 1.0f / fTemp38; + float fTemp40 = (fTemp39 + 0.25f) / fTemp38 + 1.0f; + fRec31[0] = fTemp34 - (fRec31[2] * ((fTemp39 + -0.25f) / fTemp38 + 1.0f) + 2.0f * fRec31[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp38))) / fTemp40; + fRec30[0] = (fRec31[0] - fRec31[2]) / (fTemp38 * fTemp40) - fConst36 * (fConst35 * fRec30[2] + fConst33 * fRec30[1]); + float fTemp41 = fConst36 * (fRec30[2] + fRec30[0] + 2.0f * fRec30[1] + 0.45f * (fRec28[2] + fRec28[0] + 2.0f * fRec28[1]) + 0.45f * (fRec20[2] + fRec20[0] + 2.0f * fRec20[1])); + fRec19[0] = fTemp41 - fConst31 * (fConst30 * fRec19[2] + fConst28 * fRec19[1]); + float fTemp42 = fTemp41 - fConst31 * (fRec19[2] + fRec19[0] + 2.0f * fRec19[1]); + int iTemp43 = 1103515245 * (iRec34[1] + 12345); + int iTemp44 = 1103515245 * (iTemp43 + 12345); + int iTemp45 = 1103515245 * (iTemp44 + 12345); + int iTemp46 = 1103515245 * (iTemp45 + 12345); + int iTemp47 = 1103515245 * (iTemp46 + 12345); + int iTemp48 = 1103515245 * (iTemp47 + 12345); + int iTemp49 = 1103515245 * (iTemp48 + 12345); + int iTemp50 = 1103515245 * (iTemp49 + 12345); + int iTemp51 = 1103515245 * (iTemp50 + 12345); + int iTemp52 = 1103515245 * (iTemp51 + 12345); + int iTemp53 = 1103515245 * (iTemp52 + 12345); + int iTemp54 = 1103515245 * (iTemp53 + 12345); + int iTemp55 = 1103515245 * (iTemp54 + 12345); + iRec34[0] = 1103515245 * (iTemp55 + 12345); + int iRec35 = iTemp55; + int iRec36 = iTemp54; + int iRec37 = iTemp53; + int iRec38 = iTemp52; + int iRec39 = iTemp51; + int iRec40 = iTemp50; + int iRec41 = iTemp49; + int iRec42 = iTemp48; + int iRec43 = iTemp47; + int iRec44 = iTemp46; + int iRec45 = iTemp45; + int iRec46 = iTemp44; + int iRec47 = iTemp43; + fRec33[0] = ((iTemp25) ? std::fabs(4.656613e-10f * float(iRec40)) : fRec33[1]); + fRec48[0] = ((iTemp25) ? std::fabs(4.656613e-10f * float(iRec47)) : fRec48[1]); + float fTemp56 = fRec48[0] + 1.0f; + fRec32[0] = 5e-05f * fTemp56 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec48[0] * std::fabs(std::fmod(fRec33[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec32[1]; + iRec52[0] = (iVec0[1] + iRec52[1]) % iConst42; + int iTemp57 = iRec52[0] <= iRec52[1]; + float fTemp58 = ((iTemp0) ? 0.0f : fConst43 + fRec55[1]); + fRec55[0] = fTemp58 - std::floor(fTemp58); + float fTemp59 = fRec55[0] - fRec55[1]; + fVec6[0] = fTemp59; + int iTemp60 = (fVec6[1] <= 0.0f) & (fTemp59 > 0.0f); + fRec54[0] = fRec54[1] * float(1 - iTemp60) + 4.656613e-10f * fTemp12 * float(iTemp60); + float fTemp61 = 0.5f * (fRec54[0] + 1.0f); + int iTemp62 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec55[0] >= fTemp61) * (fRec55[1] < fTemp61))) > 0.0f; + fRec53[0] = ((iTemp62 > 0) ? fConst44 : std::max(0.0f, fRec53[1] + -1.0f)); + int iTemp63 = (fRec53[0] > 0.0f) * iTemp57; + iVec7[0] = iTemp63; + iRec51[0] = (iRec51[1] + 1) * (iTemp63 == 0); + iRec56[0] = iTemp63 + iRec56[1] * (iVec7[1] >= iTemp63); + float fTemp64 = std::max(0.0f, std::min(float(iRec56[0]), 1.0f) - fConst45 * float(iRec51[0])); + float fTemp65 = 1.0f - fTemp64; + float fTemp66 = std::min(0.5f, fTemp65) - std::max(0.9f, fTemp65); + float fTemp67 = std::tan(fConst41 * (7.2e+02f * fTemp66 + 1.8e+03f)); + float fTemp68 = 1.0f / fTemp67; + float fTemp69 = (fTemp68 + 0.33333334f) / fTemp67 + 1.0f; + float fTemp70 = 18.0f * Insects_faustpower2_f(std::min(0.5f, fTemp64) - std::max(0.5f, fTemp64)); + float fTemp71 = 1.0f / (14884.0f * Insects_faustpower2_f(fTemp70 + (-1.0f - float(int(fTemp70 + -1.0f)))) + 1.0f); + fRec57[0] = fTemp71 - (fRec57[2] * ((fTemp68 + -0.33333334f) / fTemp67 + 1.0f) + 2.0f * fRec57[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp67))) / fTemp69; + fRec50[0] = (fRec57[0] - fRec57[2]) / (fTemp67 * fTemp69) - fConst36 * (fConst35 * fRec50[2] + fConst33 * fRec50[1]); + float fTemp72 = std::tan(fConst41 * (1.2e+02f * fTemp66 + 6e+02f)); + float fTemp73 = 1.0f / fTemp72; + float fTemp74 = (fTemp73 + 0.2f) / fTemp72 + 1.0f; + fRec59[0] = fTemp71 - (fRec59[2] * ((fTemp73 + -0.2f) / fTemp72 + 1.0f) + 2.0f * fRec59[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp72))) / fTemp74; + fRec58[0] = (fRec59[0] - fRec59[2]) / (fTemp72 * fTemp74) - fConst36 * (fConst35 * fRec58[2] + fConst33 * fRec58[1]); + float fTemp75 = std::tan(fConst41 * (2.7e+02f * fTemp66 + 1.2e+03f)); + float fTemp76 = 1.0f / fTemp75; + float fTemp77 = (fTemp76 + 0.25f) / fTemp75 + 1.0f; + fRec61[0] = fTemp71 - (fRec61[2] * ((fTemp76 + -0.25f) / fTemp75 + 1.0f) + 2.0f * fRec61[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp75))) / fTemp77; + fRec60[0] = (fRec61[0] - fRec61[2]) / (fTemp75 * fTemp77) - fConst36 * (fConst35 * fRec60[2] + fConst33 * fRec60[1]); + float fTemp78 = fConst36 * (fRec60[2] + fRec60[0] + 2.0f * fRec60[1] + 0.45f * (fRec58[2] + fRec58[0] + 2.0f * fRec58[1]) + 0.45f * (fRec50[2] + fRec50[0] + 2.0f * fRec50[1])); + fRec49[0] = fTemp78 - fConst31 * (fConst30 * fRec49[2] + fConst28 * fRec49[1]); + float fTemp79 = fTemp78 - fConst31 * (fRec49[2] + fRec49[0] + 2.0f * fRec49[1]); + fRec63[0] = ((iTemp62) ? std::fabs(4.656613e-10f * float(iRec39)) : fRec63[1]); + fRec64[0] = ((iTemp62) ? std::fabs(4.656613e-10f * float(iRec46)) : fRec64[1]); + float fTemp80 = fRec64[0] + 1.0f; + fRec62[0] = 5e-05f * fTemp80 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec64[0] * std::fabs(std::fmod(fRec63[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec62[1]; + iRec68[0] = (iVec0[1] + iRec68[1]) % iConst47; + int iTemp81 = iRec68[0] <= iRec68[1]; + float fTemp82 = ((iTemp0) ? 0.0f : fConst48 + fRec71[1]); + fRec71[0] = fTemp82 - std::floor(fTemp82); + float fTemp83 = fRec71[0] - fRec71[1]; + fVec8[0] = fTemp83; + int iTemp84 = (fVec8[1] <= 0.0f) & (fTemp83 > 0.0f); + fRec70[0] = fRec70[1] * float(1 - iTemp84) + 4.656613e-10f * fTemp12 * float(iTemp84); + float fTemp85 = 0.5f * (fRec70[0] + 1.0f); + int iTemp86 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec71[0] >= fTemp85) * (fRec71[1] < fTemp85))) > 0.0f; + fRec69[0] = ((iTemp86 > 0) ? fConst39 : std::max(0.0f, fRec69[1] + -1.0f)); + int iTemp87 = (fRec69[0] > 0.0f) * iTemp81; + iVec9[0] = iTemp87; + iRec67[0] = (iRec67[1] + 1) * (iTemp87 == 0); + iRec72[0] = iTemp87 + iRec72[1] * (iVec9[1] >= iTemp87); + float fTemp88 = std::max(0.0f, std::min(float(iRec72[0]), 1.0f) - fConst49 * float(iRec67[0])); + float fTemp89 = 1.0f - fTemp88; + float fTemp90 = std::min(0.5f, fTemp89) - std::max(0.9f, fTemp89); + float fTemp91 = std::tan(fConst41 * (7.2e+02f * fTemp90 + 2.7e+03f)); + float fTemp92 = 1.0f / fTemp91; + float fTemp93 = (fTemp92 + 0.33333334f) / fTemp91 + 1.0f; + float fTemp94 = 18.0f * Insects_faustpower2_f(std::min(0.5f, fTemp88) - std::max(0.5f, fTemp88)); + float fTemp95 = 1.0f / (14884.0f * Insects_faustpower2_f(fTemp94 + (-1.0f - float(int(fTemp94 + -1.0f)))) + 1.0f); + fRec73[0] = fTemp95 - (fRec73[2] * ((fTemp92 + -0.33333334f) / fTemp91 + 1.0f) + 2.0f * fRec73[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp91))) / fTemp93; + fRec66[0] = (fRec73[0] - fRec73[2]) / (fTemp91 * fTemp93) - fConst36 * (fConst35 * fRec66[2] + fConst33 * fRec66[1]); + float fTemp96 = std::tan(fConst41 * (1.2e+02f * fTemp90 + 9e+02f)); + float fTemp97 = 1.0f / fTemp96; + float fTemp98 = (fTemp97 + 0.2f) / fTemp96 + 1.0f; + fRec75[0] = fTemp95 - (fRec75[2] * ((fTemp97 + -0.2f) / fTemp96 + 1.0f) + 2.0f * fRec75[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp96))) / fTemp98; + fRec74[0] = (fRec75[0] - fRec75[2]) / (fTemp96 * fTemp98) - fConst36 * (fConst35 * fRec74[2] + fConst33 * fRec74[1]); + float fTemp99 = std::tan(fConst41 * (2.7e+02f * fTemp90 + 1.8e+03f)); + float fTemp100 = 1.0f / fTemp99; + float fTemp101 = (fTemp100 + 0.25f) / fTemp99 + 1.0f; + fRec77[0] = fTemp95 - (fRec77[2] * ((fTemp100 + -0.25f) / fTemp99 + 1.0f) + 2.0f * fRec77[1] * (1.0f - 1.0f / Insects_faustpower2_f(fTemp99))) / fTemp101; + fRec76[0] = (fRec77[0] - fRec77[2]) / (fTemp99 * fTemp101) - fConst36 * (fConst35 * fRec76[2] + fConst33 * fRec76[1]); + float fTemp102 = fConst36 * (fRec76[2] + fRec76[0] + 2.0f * fRec76[1] + 0.45f * (fRec74[2] + fRec74[0] + 2.0f * fRec74[1]) + 0.45f * (fRec66[2] + fRec66[0] + 2.0f * fRec66[1])); + fRec65[0] = fTemp102 - fConst31 * (fConst30 * fRec65[2] + fConst28 * fRec65[1]); + float fTemp103 = fTemp102 - fConst31 * (fRec65[2] + fRec65[0] + 2.0f * fRec65[1]); + fRec79[0] = ((iTemp86) ? std::fabs(4.656613e-10f * float(iRec38)) : fRec79[1]); + fRec80[0] = ((iTemp86) ? std::fabs(4.656613e-10f * float(iRec45)) : fRec80[1]); + float fTemp104 = fRec80[0] + 1.0f; + fRec78[0] = 5e-05f * fTemp104 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec80[0] * std::fabs(std::fmod(fRec79[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec78[1]; + float fTemp105 = ((iTemp0) ? 0.0f : fConst50 + fRec81[1]); + fRec81[0] = fTemp105 - std::floor(fTemp105); + float fTemp106 = ((iTemp0) ? 0.0f : fConst51 + fRec82[1]); + fRec82[0] = fTemp106 - std::floor(fTemp106); + float fTemp107 = ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec82[0]), 65535))] + ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec81[0]), 65535))]; + iRec84[0] = (iVec0[1] + iRec84[1]) % iConst52; + float fTemp108 = ((iTemp0) ? 0.0f : fConst53 + fRec87[1]); + fRec87[0] = fTemp108 - std::floor(fTemp108); + float fTemp109 = fRec87[0] - fRec87[1]; + fVec10[0] = fTemp109; + int iTemp110 = (fVec10[1] <= 0.0f) & (fTemp109 > 0.0f); + fRec86[0] = fRec86[1] * float(1 - iTemp110) + 4.656613e-10f * fTemp12 * float(iTemp110); + float fTemp111 = 0.5f * (fRec86[0] + 1.0f); + int iTemp112 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec87[0] >= fTemp111) * (fRec87[1] < fTemp111))) > 0.0f; + fRec85[0] = ((iTemp112 > 0) ? fConst54 : std::max(0.0f, fRec85[1] + -1.0f)); + int iTemp113 = (fRec85[0] > 0.0f) * (iRec84[0] <= iRec84[1]); + float fTemp114 = ((iTemp0) ? 0.0f : fConst55 + fRec88[1]); + fRec88[0] = fTemp114 - std::floor(fTemp114); + fRec83[0] = ((iTemp113) ? fRec88[0] : fRec83[1]); + float fTemp115 = 44.0f * (fRec88[0] + (1.0f - (fRec83[0] + float(int(fRec88[0] + (1.0f - fRec83[0])))))); + float fTemp116 = std::max(1.0f, std::min(4.0f, fTemp115)); + float fTemp117 = std::max(0.0f, std::min(1.0f, fTemp115)); + float fTemp118 = std::max(0.0f, std::min(1.0f, std::sin(6.2831855f * (fTemp117 + fTemp116 - (float(int(fTemp117)) + float(int(fTemp116))))))); + fRec89[0] = ((iTemp113 > 0) ? fConst56 : std::max(0.0f, fRec89[1] + -1.0f)); + float fTemp119 = float(fRec89[0] > 0.0f); + fRec91[0] = ((iTemp112) ? std::fabs(4.656613e-10f * float(iRec37)) : fRec91[1]); + fRec92[0] = ((iTemp112) ? std::fabs(4.656613e-10f * float(iRec44)) : fRec92[1]); + float fTemp120 = fRec92[0] + 1.0f; + fRec90[0] = 5e-05f * fTemp120 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec92[0] * std::fabs(std::fmod(fRec91[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec90[1]; + float fTemp121 = ((iTemp0) ? 0.0f : fConst57 + fRec93[1]); + fRec93[0] = fTemp121 - std::floor(fTemp121); + float fTemp122 = ((iTemp0) ? 0.0f : fConst58 + fRec94[1]); + fRec94[0] = fTemp122 - std::floor(fTemp122); + float fTemp123 = ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec94[0]), 65535))] + ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec93[0]), 65535))]; + float fTemp124 = ((iTemp0) ? 0.0f : fConst59 + fRec98[1]); + fRec98[0] = fTemp124 - std::floor(fTemp124); + float fTemp125 = fRec98[0] - fRec98[1]; + fVec11[0] = fTemp125; + int iTemp126 = (fVec11[1] <= 0.0f) & (fTemp125 > 0.0f); + fRec97[0] = fRec97[1] * float(1 - iTemp126) + 4.656613e-10f * fTemp12 * float(iTemp126); + float fTemp127 = 0.5f * (fRec97[0] + 1.0f); + int iTemp128 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec98[0] >= fTemp127) * (fRec98[1] < fTemp127))) > 0.0f; + fRec96[0] = ((iTemp128 > 0) ? fConst60 : std::max(0.0f, fRec96[1] + -1.0f)); + int iTemp129 = (fRec96[0] > 0.0f) * iTemp81; + fRec95[0] = ((iTemp129) ? fRec88[0] : fRec95[1]); + float fTemp130 = 44.0f * (fRec88[0] + (1.0f - (fRec95[0] + float(int(fRec88[0] + (1.0f - fRec95[0])))))); + float fTemp131 = std::max(1.0f, std::min(4.0f, fTemp130)); + float fTemp132 = std::max(0.0f, std::min(1.0f, fTemp130)); + float fTemp133 = std::max(0.0f, std::min(1.0f, std::sin(6.2831855f * (fTemp132 + fTemp131 - (float(int(fTemp132)) + float(int(fTemp131))))))); + fRec99[0] = ((iTemp129 > 0) ? fConst56 : std::max(0.0f, fRec99[1] + -1.0f)); + float fTemp134 = float(fRec99[0] > 0.0f); + fRec101[0] = ((iTemp128) ? std::fabs(4.656613e-10f * float(iRec36)) : fRec101[1]); + fRec102[0] = ((iTemp128) ? std::fabs(4.656613e-10f * float(iRec43)) : fRec102[1]); + float fTemp135 = fRec102[0] + 1.0f; + fRec100[0] = 5e-05f * fTemp135 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec102[0] * std::fabs(std::fmod(fRec101[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec100[1]; + float fTemp136 = ((iTemp0) ? 0.0f : fConst61 + fRec103[1]); + fRec103[0] = fTemp136 - std::floor(fTemp136); + float fTemp137 = ((iTemp0) ? 0.0f : fConst62 + fRec104[1]); + fRec104[0] = fTemp137 - std::floor(fTemp137); + float fTemp138 = ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec104[0]), 65535))] + ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec103[0]), 65535))]; + float fTemp139 = ((iTemp0) ? 0.0f : fConst63 + fRec108[1]); + fRec108[0] = fTemp139 - std::floor(fTemp139); + float fTemp140 = fRec108[0] - fRec108[1]; + fVec12[0] = fTemp140; + int iTemp141 = (fVec12[1] <= 0.0f) & (fTemp140 > 0.0f); + fRec107[0] = fRec107[1] * float(1 - iTemp141) + 4.656613e-10f * fTemp12 * float(iTemp141); + float fTemp142 = 0.5f * (fRec107[0] + 1.0f); + int iTemp143 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec108[0] >= fTemp142) * (fRec108[1] < fTemp142))) > 0.0f; + fRec106[0] = ((iTemp143 > 0) ? fConst64 : std::max(0.0f, fRec106[1] + -1.0f)); + int iTemp144 = (fRec106[0] > 0.0f) * iTemp57; + fRec105[0] = ((iTemp144) ? fRec88[0] : fRec105[1]); + float fTemp145 = 44.0f * (fRec88[0] + (1.0f - (fRec105[0] + float(int(fRec88[0] + (1.0f - fRec105[0])))))); + float fTemp146 = std::max(1.0f, std::min(4.0f, fTemp145)); + float fTemp147 = std::max(0.0f, std::min(1.0f, fTemp145)); + float fTemp148 = std::max(0.0f, std::min(1.0f, std::sin(6.2831855f * (fTemp147 + fTemp146 - (float(int(fTemp147)) + float(int(fTemp146))))))); + fRec109[0] = ((iTemp144 > 0) ? fConst56 : std::max(0.0f, fRec109[1] + -1.0f)); + float fTemp149 = float(fRec109[0] > 0.0f); + fRec111[0] = ((iTemp143) ? std::fabs(4.656613e-10f * float(iRec35)) : fRec111[1]); + fRec112[0] = ((iTemp143) ? std::fabs(4.656613e-10f * float(iRec42)) : fRec112[1]); + float fTemp150 = fRec112[0] + 1.0f; + fRec110[0] = 5e-05f * fTemp150 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec112[0] * std::fabs(std::fmod(fRec111[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec110[1]; + float fTemp151 = ((iTemp0) ? 0.0f : fConst65 + fRec113[1]); + fRec113[0] = fTemp151 - std::floor(fTemp151); + float fTemp152 = ((iTemp0) ? 0.0f : fConst66 + fRec114[1]); + fRec114[0] = fTemp152 - std::floor(fTemp152); + float fTemp153 = ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec114[0]), 65535))] + ftbl0InsectsSIG0[std::max(0, std::min(int(65536.0f * fRec113[0]), 65535))]; + iRec116[0] = (iVec0[1] + iRec116[1]) % iConst67; + float fTemp154 = ((iTemp0) ? 0.0f : fConst68 + fRec119[1]); + fRec119[0] = fTemp154 - std::floor(fTemp154); + float fTemp155 = fRec119[0] - fRec119[1]; + fVec13[0] = fTemp155; + int iTemp156 = (fVec13[1] <= 0.0f) & (fTemp155 > 0.0f); + fRec118[0] = fRec118[1] * float(1 - iTemp156) + 4.656613e-10f * fTemp12 * float(iTemp156); + float fTemp157 = 0.5f * (fRec118[0] + 1.0f); + int iTemp158 = std::fabs(4.656613e-10f * fVec2[1] * float((fRec119[0] >= fTemp157) * (fRec119[1] < fTemp157))) > 0.0f; + fRec117[0] = ((iTemp158 > 0) ? fConst69 : std::max(0.0f, fRec117[1] + -1.0f)); + int iTemp159 = (fRec117[0] > 0.0f) * (iRec116[0] <= iRec116[1]); + fRec115[0] = ((iTemp159) ? fRec88[0] : fRec115[1]); + float fTemp160 = 44.0f * (fRec88[0] + (1.0f - (fRec115[0] + float(int(fRec88[0] + (1.0f - fRec115[0])))))); + float fTemp161 = std::max(1.0f, std::min(4.0f, fTemp160)); + float fTemp162 = std::max(0.0f, std::min(1.0f, fTemp160)); + float fTemp163 = std::max(0.0f, std::min(1.0f, std::sin(6.2831855f * (fTemp162 + fTemp161 - (float(int(fTemp162)) + float(int(fTemp161))))))); + fRec120[0] = ((iTemp159 > 0) ? fConst56 : std::max(0.0f, fRec120[1] + -1.0f)); + float fTemp164 = float(fRec120[0] > 0.0f); + fRec122[0] = ((iTemp158) ? std::fabs(4.656613e-10f * float(iRec34[0])) : fRec122[1]); + fRec123[0] = ((iTemp158) ? std::fabs(4.656613e-10f * float(iRec41)) : fRec123[1]); + float fTemp165 = fRec123[0] + 1.0f; + fRec121[0] = 5e-05f * fTemp165 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec123[0] * std::fabs(std::fmod(fRec122[0] + 1.5f, 1.0f) + -0.5f))) + 0.9999f * fRec121[1]; + fRec130[0] = fConst72 * fRec131[1] + fConst71 * fRec130[1]; + fRec131[0] = float(iTemp0) + fConst71 * fRec131[1] - fConst72 * fRec130[1]; + int iTemp166 = (fRec130[1] <= 0.0f) & (fRec130[0] > 0.0f); + fRec129[0] = fRec129[1] * float(1 - iTemp166) + 4.656613e-10f * fTemp12 * float(iTemp166); + fRec128[0] = -(fConst75 * (fConst74 * fRec128[1] - (fRec129[0] + fRec129[1]))); + fRec127[0] = -(fConst75 * (fConst74 * fRec127[1] - (fRec128[0] + fRec128[1]))); + fRec126[0] = -(fConst75 * (fConst74 * fRec126[1] - (fRec127[0] + fRec127[1]))); + fRec125[0] = -(fConst75 * (fConst74 * fRec125[1] - (fRec126[0] + fRec126[1]))); + fRec124[0] = -(fConst75 * (fConst74 * fRec124[1] - (fRec125[0] + fRec125[1]))); + output0[i0] = FAUSTFLOAT(0.3f * fRec124[0] * (fRec121[0] * fTemp164 * fTemp163 * fTemp153 + fRec110[0] * fTemp149 * fTemp148 * fTemp138 + fRec100[0] * fTemp134 * fTemp133 * fTemp123 + fRec90[0] * fTemp119 * fTemp118 * fTemp107) + 0.5f * (fRec78[0] * fTemp103 + fRec62[0] * fTemp79 + fRec32[0] * fTemp42) + fTemp20); + fRec132[0] = 5e-05f * fTemp120 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec92[0] * std::fabs(std::fmod(fRec91[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec132[1]; + fRec133[0] = 5e-05f * fTemp135 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec102[0] * std::fabs(std::fmod(fRec101[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec133[1]; + fRec134[0] = 5e-05f * fTemp150 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec112[0] * std::fabs(std::fmod(fRec111[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec134[1]; + fRec135[0] = 5e-05f * fTemp165 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec123[0] * std::fabs(std::fmod(fRec122[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec135[1]; + fRec136[0] = 5e-05f * fTemp56 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec48[0] * std::fabs(std::fmod(fRec33[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec136[1]; + fRec137[0] = 5e-05f * fTemp80 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec64[0] * std::fabs(std::fmod(fRec63[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec137[1]; + fRec138[0] = 5e-05f * fTemp104 * std::sqrt(std::max(0.0f, 1.0f - 2.0f * fRec80[0] * std::fabs(std::fmod(fRec79[0] + 1.0f, 1.0f) + -0.5f))) + 0.9999f * fRec138[1]; + output1[i0] = FAUSTFLOAT(0.5f * (fRec138[0] * fTemp103 + fRec137[0] * fTemp79 + fRec136[0] * fTemp42) + fTemp20 + 0.3f * fRec124[0] * (fRec135[0] * fTemp164 * fTemp163 * fTemp153 + fRec134[0] * fTemp149 * fTemp148 * fTemp138 + fRec133[0] * fTemp134 * fTemp133 * fTemp123 + fRec132[0] * fTemp119 * fTemp118 * fTemp107)); + iVec0[1] = iVec0[0]; + fRec1[1] = fRec1[0]; + fRec2[1] = fRec2[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fRec0[2] = fRec0[1]; + fRec0[1] = fRec0[0]; + fRec6[1] = fRec6[0]; + fRec7[1] = fRec7[0]; + fRec8[1] = fRec8[0]; + fRec9[1] = fRec9[0]; + fRec5[2] = fRec5[1]; + fRec5[1] = fRec5[0]; + fRec11[1] = fRec11[0]; + iRec13[1] = iRec13[0]; + fVec2[1] = fVec2[0]; + fRec12[2] = fRec12[1]; + fRec12[1] = fRec12[0]; + fRec18[1] = fRec18[0]; + fVec3[1] = fVec3[0]; + fRec17[1] = fRec17[0]; + fRec16[1] = fRec16[0]; + fRec15[1] = fRec15[0]; + fRec14[2] = fRec14[1]; + fRec14[1] = fRec14[0]; + iRec22[1] = iRec22[0]; + fRec25[1] = fRec25[0]; + fVec4[1] = fVec4[0]; + fRec24[1] = fRec24[0]; + fRec23[1] = fRec23[0]; + iVec5[1] = iVec5[0]; + iRec21[1] = iRec21[0]; + iRec26[1] = iRec26[0]; + fRec27[2] = fRec27[1]; + fRec27[1] = fRec27[0]; + fRec20[2] = fRec20[1]; + fRec20[1] = fRec20[0]; + fRec29[2] = fRec29[1]; + fRec29[1] = fRec29[0]; + fRec28[2] = fRec28[1]; + fRec28[1] = fRec28[0]; + fRec31[2] = fRec31[1]; + fRec31[1] = fRec31[0]; + fRec30[2] = fRec30[1]; + fRec30[1] = fRec30[0]; + fRec19[2] = fRec19[1]; + fRec19[1] = fRec19[0]; + iRec34[1] = iRec34[0]; + fRec33[1] = fRec33[0]; + fRec48[1] = fRec48[0]; + fRec32[1] = fRec32[0]; + iRec52[1] = iRec52[0]; + fRec55[1] = fRec55[0]; + fVec6[1] = fVec6[0]; + fRec54[1] = fRec54[0]; + fRec53[1] = fRec53[0]; + iVec7[1] = iVec7[0]; + iRec51[1] = iRec51[0]; + iRec56[1] = iRec56[0]; + fRec57[2] = fRec57[1]; + fRec57[1] = fRec57[0]; + fRec50[2] = fRec50[1]; + fRec50[1] = fRec50[0]; + fRec59[2] = fRec59[1]; + fRec59[1] = fRec59[0]; + fRec58[2] = fRec58[1]; + fRec58[1] = fRec58[0]; + fRec61[2] = fRec61[1]; + fRec61[1] = fRec61[0]; + fRec60[2] = fRec60[1]; + fRec60[1] = fRec60[0]; + fRec49[2] = fRec49[1]; + fRec49[1] = fRec49[0]; + fRec63[1] = fRec63[0]; + fRec64[1] = fRec64[0]; + fRec62[1] = fRec62[0]; + iRec68[1] = iRec68[0]; + fRec71[1] = fRec71[0]; + fVec8[1] = fVec8[0]; + fRec70[1] = fRec70[0]; + fRec69[1] = fRec69[0]; + iVec9[1] = iVec9[0]; + iRec67[1] = iRec67[0]; + iRec72[1] = iRec72[0]; + fRec73[2] = fRec73[1]; + fRec73[1] = fRec73[0]; + fRec66[2] = fRec66[1]; + fRec66[1] = fRec66[0]; + fRec75[2] = fRec75[1]; + fRec75[1] = fRec75[0]; + fRec74[2] = fRec74[1]; + fRec74[1] = fRec74[0]; + fRec77[2] = fRec77[1]; + fRec77[1] = fRec77[0]; + fRec76[2] = fRec76[1]; + fRec76[1] = fRec76[0]; + fRec65[2] = fRec65[1]; + fRec65[1] = fRec65[0]; + fRec79[1] = fRec79[0]; + fRec80[1] = fRec80[0]; + fRec78[1] = fRec78[0]; + fRec81[1] = fRec81[0]; + fRec82[1] = fRec82[0]; + iRec84[1] = iRec84[0]; + fRec87[1] = fRec87[0]; + fVec10[1] = fVec10[0]; + fRec86[1] = fRec86[0]; + fRec85[1] = fRec85[0]; + fRec88[1] = fRec88[0]; + fRec83[1] = fRec83[0]; + fRec89[1] = fRec89[0]; + fRec91[1] = fRec91[0]; + fRec92[1] = fRec92[0]; + fRec90[1] = fRec90[0]; + fRec93[1] = fRec93[0]; + fRec94[1] = fRec94[0]; + fRec98[1] = fRec98[0]; + fVec11[1] = fVec11[0]; + fRec97[1] = fRec97[0]; + fRec96[1] = fRec96[0]; + fRec95[1] = fRec95[0]; + fRec99[1] = fRec99[0]; + fRec101[1] = fRec101[0]; + fRec102[1] = fRec102[0]; + fRec100[1] = fRec100[0]; + fRec103[1] = fRec103[0]; + fRec104[1] = fRec104[0]; + fRec108[1] = fRec108[0]; + fVec12[1] = fVec12[0]; + fRec107[1] = fRec107[0]; + fRec106[1] = fRec106[0]; + fRec105[1] = fRec105[0]; + fRec109[1] = fRec109[0]; + fRec111[1] = fRec111[0]; + fRec112[1] = fRec112[0]; + fRec110[1] = fRec110[0]; + fRec113[1] = fRec113[0]; + fRec114[1] = fRec114[0]; + iRec116[1] = iRec116[0]; + fRec119[1] = fRec119[0]; + fVec13[1] = fVec13[0]; + fRec118[1] = fRec118[0]; + fRec117[1] = fRec117[0]; + fRec115[1] = fRec115[0]; + fRec120[1] = fRec120[0]; + fRec122[1] = fRec122[0]; + fRec123[1] = fRec123[0]; + fRec121[1] = fRec121[0]; + fRec130[1] = fRec130[0]; + fRec131[1] = fRec131[0]; + fRec129[1] = fRec129[0]; + fRec128[1] = fRec128[0]; + fRec127[1] = fRec127[0]; + fRec126[1] = fRec126[0]; + fRec125[1] = fRec125[0]; + fRec124[1] = fRec124[0]; + fRec132[1] = fRec132[0]; + fRec133[1] = fRec133[0]; + fRec134[1] = fRec134[0]; + fRec135[1] = fRec135[0]; + fRec136[1] = fRec136[0]; + fRec137[1] = fRec137[0]; + fRec138[1] = fRec138[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/sine440.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/sine440.cpp new file mode 100644 index 0000000000..13ef0ad0ab --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/sine440.cpp @@ -0,0 +1,186 @@ +/* ------------------------------------------------------------ +author: "Grame" +copyright: "(c)GRAME 2009" +license: "BSD" +name: "untitled", "osc" +version: "1.0" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __Sine440_H__ +#define __Sine440_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS Sine440 +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +class Sine440SIG0 { + + private: + + int iVec0[2]; + int iRec0[2]; + + public: + + int getNumInputsSine440SIG0() { + return 0; + } + int getNumOutputsSine440SIG0() { + return 1; + } + + void instanceInitSine440SIG0(int sample_rate) { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + iRec0[l1] = 0; + } + } + + void fillSine440SIG0(int count, float* table) { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iVec0[0] = 1; + iRec0[0] = (iVec0[1] + iRec0[1]) % 65536; + table[i1] = std::sin(9.58738e-05f * float(iRec0[0])); + iVec0[1] = iVec0[0]; + iRec0[1] = iRec0[0]; + } + } + +}; + +static Sine440SIG0* newSine440SIG0() { return (Sine440SIG0*)new Sine440SIG0(); } +static void deleteSine440SIG0(Sine440SIG0* dsp) { delete dsp; } + +static float ftbl0Sine440SIG0[65536]; + +class Sine440 : public dsp { + + private: + + int iVec1[2]; + int fSampleRate; + float fConst0; + float fRec1[2]; + + public: + Sine440() { + } + + void metadata(Meta* m) { + m->declare("author", "Grame"); + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("copyright", "(c)GRAME 2009"); + m->declare("filename", "untitled.dsp"); + m->declare("license", "BSD"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/version", "1.6.0"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("version", "1.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 1; + } + + static void classInit(int sample_rate) { + Sine440SIG0* sig0 = newSine440SIG0(); + sig0->instanceInitSine440SIG0(sample_rate); + sig0->fillSine440SIG0(65536, ftbl0Sine440SIG0); + deleteSine440SIG0(sig0); + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = 4.4e+02f / std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + } + + virtual void instanceResetUserInterface() { + } + + virtual void instanceClear() { + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + iVec1[l2] = 0; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec1[l3] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual Sine440* clone() { + return new Sine440(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec1[0] = 1; + float fTemp0 = ((1 - iVec1[1]) ? 0.0f : fConst0 + fRec1[1]); + fRec1[0] = fTemp0 - std::floor(fTemp0); + output0[i0] = FAUSTFLOAT(0.1f * ftbl0Sine440SIG0[std::max(0, std::min(int(65536.0f * fRec1[0]), 65535))]); + iVec1[1] = iVec1[0]; + fRec1[1] = fRec1[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/waveSynthAnalog.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/waveSynthAnalog.cpp new file mode 100644 index 0000000000..694bad5a03 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/waveSynthAnalog.cpp @@ -0,0 +1,390 @@ +/* ------------------------------------------------------------ +name: "untitled" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __WaveSynthAnalog_H__ +#define __WaveSynthAnalog_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS WaveSynthAnalog +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +class WaveSynthAnalogSIG0 { + + private: + + int iRec3[2]; + + public: + + int getNumInputsWaveSynthAnalogSIG0() { + return 0; + } + int getNumOutputsWaveSynthAnalogSIG0() { + return 1; + } + + void instanceInitWaveSynthAnalogSIG0(int sample_rate) { + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + iRec3[l4] = 0; + } + } + + void fillWaveSynthAnalogSIG0(int count, float* table) { + for (int i1 = 0; i1 < count; i1 = i1 + 1) { + iRec3[0] = iRec3[1] + 1; + table[i1] = std::fabs(std::fmod(0.00390625f * float(iRec3[1]) + 1.0f, 4.0f) + -2.0f) + -1.0f; + iRec3[1] = iRec3[0]; + } + } + +}; + +static WaveSynthAnalogSIG0* newWaveSynthAnalogSIG0() { return (WaveSynthAnalogSIG0*)new WaveSynthAnalogSIG0(); } +static void deleteWaveSynthAnalogSIG0(WaveSynthAnalogSIG0* dsp) { delete dsp; } + +class WaveSynthAnalogSIG1 { + + private: + + int iRec5[2]; + + public: + + int getNumInputsWaveSynthAnalogSIG1() { + return 0; + } + int getNumOutputsWaveSynthAnalogSIG1() { + return 1; + } + + void instanceInitWaveSynthAnalogSIG1(int sample_rate) { + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + iRec5[l6] = 0; + } + } + + void fillWaveSynthAnalogSIG1(int count, float* table) { + for (int i2 = 0; i2 < count; i2 = i2 + 1) { + iRec5[0] = iRec5[1] + 1; + table[i2] = std::fabs(std::fmod(0.005859375f * float(iRec5[1]) + 1.0f, 4.0f) + -2.0f) + -1.0f; + iRec5[1] = iRec5[0]; + } + } + +}; + +static WaveSynthAnalogSIG1* newWaveSynthAnalogSIG1() { return (WaveSynthAnalogSIG1*)new WaveSynthAnalogSIG1(); } +static void deleteWaveSynthAnalogSIG1(WaveSynthAnalogSIG1* dsp) { delete dsp; } + +class WaveSynthAnalogSIG2 { + + private: + + int iRec6[2]; + + public: + + int getNumInputsWaveSynthAnalogSIG2() { + return 0; + } + int getNumOutputsWaveSynthAnalogSIG2() { + return 1; + } + + void instanceInitWaveSynthAnalogSIG2(int sample_rate) { + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + iRec6[l7] = 0; + } + } + + void fillWaveSynthAnalogSIG2(int count, float* table) { + for (int i3 = 0; i3 < count; i3 = i3 + 1) { + iRec6[0] = iRec6[1] + 1; + table[i3] = std::fabs(std::fmod(0.0078125f * float(iRec6[1]) + 1.0f, 4.0f) + -2.0f) + -1.0f; + iRec6[1] = iRec6[0]; + } + } + +}; + +static WaveSynthAnalogSIG2* newWaveSynthAnalogSIG2() { return (WaveSynthAnalogSIG2*)new WaveSynthAnalogSIG2(); } +static void deleteWaveSynthAnalogSIG2(WaveSynthAnalogSIG2* dsp) { delete dsp; } + +class WaveSynthAnalogSIG3 { + + private: + + int iRec7[2]; + + public: + + int getNumInputsWaveSynthAnalogSIG3() { + return 0; + } + int getNumOutputsWaveSynthAnalogSIG3() { + return 1; + } + + void instanceInitWaveSynthAnalogSIG3(int sample_rate) { + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + iRec7[l8] = 0; + } + } + + void fillWaveSynthAnalogSIG3(int count, float* table) { + for (int i4 = 0; i4 < count; i4 = i4 + 1) { + iRec7[0] = iRec7[1] + 1; + table[i4] = std::fabs(std::fmod(0.015625f * float(iRec7[1]) + 1.0f, 4.0f) + -2.0f) + -1.0f; + iRec7[1] = iRec7[0]; + } + } + +}; + +static WaveSynthAnalogSIG3* newWaveSynthAnalogSIG3() { return (WaveSynthAnalogSIG3*)new WaveSynthAnalogSIG3(); } +static void deleteWaveSynthAnalogSIG3(WaveSynthAnalogSIG3* dsp) { delete dsp; } + +static float ftbl0WaveSynthAnalogSIG0[1024]; +static float ftbl1WaveSynthAnalogSIG1[1024]; +static float ftbl2WaveSynthAnalogSIG2[1024]; +static float ftbl3WaveSynthAnalogSIG3[1024]; + +class WaveSynthAnalog : public dsp { + + private: + + int iVec0[2]; + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + FAUSTFLOAT fHslider0; + float fRec1[2]; + float fConst3; + float fRec0[2]; + FAUSTFLOAT fHslider1; + float fRec2[2]; + FAUSTFLOAT fHslider2; + FAUSTFLOAT fHslider3; + FAUSTFLOAT fEntry0; + float fRec4[2]; + FAUSTFLOAT fHslider4; + int iRec9[2]; + FAUSTFLOAT fHslider5; + FAUSTFLOAT fHslider6; + float fRec8[2]; + FAUSTFLOAT fEntry1; + + public: + WaveSynthAnalog() { + } + + void metadata(Meta* m) { + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("envelopes.lib/adsre:author", "Julius O. Smith III"); + m->declare("envelopes.lib/adsre:licence", "STK-4.3"); + m->declare("envelopes.lib/author", "GRAME"); + m->declare("envelopes.lib/copyright", "GRAME"); + m->declare("envelopes.lib/license", "LGPL with exception"); + m->declare("envelopes.lib/name", "Faust Envelope Library"); + m->declare("envelopes.lib/version", "1.3.0"); + m->declare("filename", "untitled.dsp"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("oscillators.lib/lf_sawpos:author", "Bart Brouns, revised by Stéphane Letz"); + m->declare("oscillators.lib/lf_sawpos:licence", "STK-4.3"); + m->declare("oscillators.lib/name", "Faust Oscillator Library"); + m->declare("oscillators.lib/saw1:author", "Bart Brouns"); + m->declare("oscillators.lib/saw1:licence", "STK-4.3"); + m->declare("oscillators.lib/version", "1.6.0"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "1.6.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 1; + } + + static void classInit(int sample_rate) { + WaveSynthAnalogSIG0* sig0 = newWaveSynthAnalogSIG0(); + sig0->instanceInitWaveSynthAnalogSIG0(sample_rate); + sig0->fillWaveSynthAnalogSIG0(1024, ftbl0WaveSynthAnalogSIG0); + WaveSynthAnalogSIG1* sig1 = newWaveSynthAnalogSIG1(); + sig1->instanceInitWaveSynthAnalogSIG1(sample_rate); + sig1->fillWaveSynthAnalogSIG1(1024, ftbl1WaveSynthAnalogSIG1); + WaveSynthAnalogSIG2* sig2 = newWaveSynthAnalogSIG2(); + sig2->instanceInitWaveSynthAnalogSIG2(sample_rate); + sig2->fillWaveSynthAnalogSIG2(1024, ftbl2WaveSynthAnalogSIG2); + WaveSynthAnalogSIG3* sig3 = newWaveSynthAnalogSIG3(); + sig3->instanceInitWaveSynthAnalogSIG3(sample_rate); + sig3->fillWaveSynthAnalogSIG3(1024, ftbl3WaveSynthAnalogSIG3); + deleteWaveSynthAnalogSIG0(sig0); + deleteWaveSynthAnalogSIG1(sig1); + deleteWaveSynthAnalogSIG2(sig2); + deleteWaveSynthAnalogSIG3(sig3); + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = 44.1f / fConst0; + fConst2 = 1.0f - fConst1; + fConst3 = 1.0f / fConst0; + } + + virtual void instanceResetUserInterface() { + fHslider0 = FAUSTFLOAT(0.1f); + fHslider1 = FAUSTFLOAT(0.0f); + fHslider2 = FAUSTFLOAT(0.0f); + fHslider3 = FAUSTFLOAT(0.0f); + fEntry0 = FAUSTFLOAT(4.4e+02f); + fHslider4 = FAUSTFLOAT(0.01f); + fHslider5 = FAUSTFLOAT(0.6f); + fHslider6 = FAUSTFLOAT(0.2f); + fEntry1 = FAUSTFLOAT(0.5f); + } + + virtual void instanceClear() { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + fRec1[l1] = 0.0f; + } + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + fRec0[l2] = 0.0f; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec2[l3] = 0.0f; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + fRec4[l5] = 0.0f; + } + for (int l9 = 0; l9 < 2; l9 = l9 + 1) { + iRec9[l9] = 0; + } + for (int l10 = 0; l10 < 2; l10 = l10 + 1) { + fRec8[l10] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual WaveSynthAnalog* clone() { + return new WaveSynthAnalog(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->declare(&fHslider4, "midi", "ctrl 73"); + ui_interface->addHorizontalSlider("A", &fHslider4, FAUSTFLOAT(0.01f), FAUSTFLOAT(0.01f), FAUSTFLOAT(4.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider5, "midi", "ctrl 76"); + ui_interface->addHorizontalSlider("D", &fHslider5, FAUSTFLOAT(0.6f), FAUSTFLOAT(0.01f), FAUSTFLOAT(8.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider6, "midi", "ctrl 77"); + ui_interface->addHorizontalSlider("S", &fHslider6, FAUSTFLOAT(0.2f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider3, "midi", "pitchwheel"); + ui_interface->addHorizontalSlider("bend", &fHslider3, FAUSTFLOAT(0.0f), FAUSTFLOAT(-2.0f), FAUSTFLOAT(2.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fEntry0, "unit", "Hz"); + ui_interface->addNumEntry("freq", &fEntry0, FAUSTFLOAT(4.4e+02f), FAUSTFLOAT(2e+01f), FAUSTFLOAT(2e+04f), FAUSTFLOAT(1.0f)); + ui_interface->addNumEntry("gain", &fEntry1, FAUSTFLOAT(0.5f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); + ui_interface->declare(&fHslider1, "BELA", "ANALOG_2"); + ui_interface->addHorizontalSlider("lfoDepth", &fHslider1, FAUSTFLOAT(0.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.001f)); + ui_interface->declare(&fHslider0, "BELA", "ANALOG_1"); + ui_interface->addHorizontalSlider("lfoFreq", &fHslider0, FAUSTFLOAT(0.1f), FAUSTFLOAT(0.01f), FAUSTFLOAT(1e+01f), FAUSTFLOAT(0.001f)); + ui_interface->declare(&fHslider2, "BELA", "ANALOG_0"); + ui_interface->addHorizontalSlider("waveTravel", &fHslider2, FAUSTFLOAT(0.0f), FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f), FAUSTFLOAT(0.01f)); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = fConst1 * float(fHslider0); + float fSlow1 = fConst1 * float(fHslider1); + float fSlow2 = float(fHslider2); + float fSlow3 = fConst3 * float(fEntry0) * std::pow(2.0f, 0.083333336f * float(fHslider3)); + float fSlow4 = float(fHslider4); + int iSlow5 = int(fConst0 * fSlow4); + float fSlow6 = float(fHslider5); + float fSlow7 = float(fHslider6); + float fSlow8 = float(fEntry1); + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec0[0] = 1; + int iTemp0 = 1 - iVec0[1]; + fRec1[0] = fSlow0 + fConst2 * fRec1[1]; + float fTemp1 = ((iTemp0) ? 0.0f : fRec0[1] + fConst3 * fRec1[0]); + fRec0[0] = fTemp1 - std::floor(fTemp1); + fRec2[0] = fSlow1 + fConst2 * fRec2[1]; + float fTemp2 = std::max(0.0f, std::min(1.0f, fSlow2 + fRec2[0] * (1.0f - std::fabs(2.0f * fRec0[0] + -1.0f)))); + float fTemp3 = ((iTemp0) ? 0.0f : fSlow3 + fRec4[1]); + fRec4[0] = fTemp3 - std::floor(fTemp3); + int iTemp4 = std::max(0, std::min(int(1024.0f * fRec4[0]), 1023)); + iRec9[0] = iRec9[1] + 1; + int iTemp5 = (iRec9[0] < iSlow5) | (iTemp0 * (iTemp0 > 0)); + float fTemp6 = 0.1447178f * ((iTemp5) ? fSlow4 : fSlow6); + int iTemp7 = std::fabs(fTemp6) < 1.1920929e-07f; + float fTemp8 = ((iTemp7) ? 0.0f : std::exp(-(fConst3 / ((iTemp7) ? 1.0f : fTemp6)))); + fRec8[0] = (1.0f - fTemp8) * ((iTemp5) ? 1.0f : fSlow7) + fTemp8 * fRec8[1]; + output0[i0] = FAUSTFLOAT(fSlow8 * fRec8[0] * (ftbl3WaveSynthAnalogSIG3[iTemp4] * std::max(0.0f, std::cos(4.712385f * fTemp2)) + ftbl2WaveSynthAnalogSIG2[iTemp4] * std::max(0.0f, std::cos(4.712385f * (fTemp2 + -0.33333334f))) + ftbl1WaveSynthAnalogSIG1[iTemp4] * std::max(0.0f, std::cos(4.712385f * (fTemp2 + -0.6666667f))) + ftbl0WaveSynthAnalogSIG0[iTemp4] * std::max(0.0f, std::cos(4.712385f * (fTemp2 + -1.0f))))); + iVec0[1] = iVec0[0]; + fRec1[1] = fRec1[0]; + fRec0[1] = fRec0[0]; + fRec2[1] = fRec2[0]; + fRec4[1] = fRec4[0]; + iRec9[1] = iRec9[0]; + fRec8[1] = fRec8[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/wind.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/wind.cpp new file mode 100644 index 0000000000..de47277081 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/wind.cpp @@ -0,0 +1,273 @@ +/* ------------------------------------------------------------ +name: "untitled", "wind" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __Wind_H__ +#define __Wind_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS Wind +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + +static float Wind_faustpower2_f(float value) { + return value * value; +} + +class Wind : public dsp { + + private: + + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + float fConst3; + float fConst4; + float fConst5; + float fConst6; + float fConst7; + float fConst8; + float fConst9; + float fConst10; + float fConst11; + float fConst12; + int iRec6[2]; + float fConst13; + float fConst14; + float fConst15; + float fConst16; + float fConst17; + float fRec5[2]; + float fRec3[2]; + float fConst18; + float fConst19; + float fConst20; + float fConst21; + float fConst22; + float fConst23; + float fConst24; + float fConst25; + float fConst26; + float fConst27; + float fRec2[2]; + float fRec0[2]; + float fConst28; + float fConst29; + float fConst30; + float fConst31; + float fConst32; + float fConst33; + float fRec13[2]; + float fRec11[2]; + float fRec10[2]; + float fRec8[2]; + + public: + Wind() { + } + + void metadata(Meta* m) { + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("filename", "untitled.dsp"); + m->declare("filters.lib/allpassnnlt:author", "Julius O. Smith III"); + m->declare("filters.lib/allpassnnlt:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/allpassnnlt:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license"); + m->declare("filters.lib/name", "Faust Filters Library"); + m->declare("filters.lib/tf2np:author", "Julius O. Smith III"); + m->declare("filters.lib/tf2np:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/tf2np:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/version", "1.7.1"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("noises.lib/name", "Faust Noise Generator Library"); + m->declare("noises.lib/version", "1.4.1"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("vaeffects.lib/moog_vcf_2bn:author", "Julius O. Smith III"); + m->declare("vaeffects.lib/moog_vcf_2bn:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("vaeffects.lib/moog_vcf_2bn:license", "MIT-style STK-4.3 license"); + m->declare("vaeffects.lib/name", "Faust Virtual Analog Filter Effect Library"); + m->declare("vaeffects.lib/version", "1.3.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 2; + } + + static void classInit(int sample_rate) { + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::tan(2912.1235f / std::min(1.92e+05f, std::max(1.0f, float(fSampleRate)))); + fConst1 = 1.0f / fConst0; + fConst2 = (fConst1 + 0.600014f) / fConst0 + 0.5799944f; + fConst3 = ((fConst1 + -0.600014f) / fConst0 + 0.5799944f) / fConst2; + fConst4 = 1.0f / Wind_faustpower2_f(fConst0); + fConst5 = 0.5799944f - fConst4; + fConst6 = std::max(-0.9999999f, std::min(0.9999999f, 2.0f * (fConst5 / (fConst2 * (fConst3 + 1.0f))))); + fConst7 = std::max(-0.9999999f, std::min(0.9999999f, fConst3)); + fConst8 = (fConst1 + 3.399986f) / fConst0 + 3.3799665f; + fConst9 = ((fConst1 + -3.399986f) / fConst0 + 3.3799665f) / fConst8; + fConst10 = 3.3799665f - fConst4; + fConst11 = std::max(-0.9999999f, std::min(0.9999999f, 2.0f * (fConst10 / (fConst8 * (fConst9 + 1.0f))))); + fConst12 = std::max(-0.9999999f, std::min(0.9999999f, fConst9)); + fConst13 = 1.0f - Wind_faustpower2_f(fConst12); + fConst14 = std::sqrt(std::max(0.0f, fConst13)); + fConst15 = 4.656613e-10f * fConst14; + fConst16 = 1.0f - Wind_faustpower2_f(fConst11); + fConst17 = std::sqrt(std::max(0.0f, fConst16)); + fConst18 = std::sqrt(fConst13); + fConst19 = 1.0f - fConst10 / fConst8; + fConst20 = (1.0f - fConst9 - 2.0f * fConst11 * fConst19) / (fConst18 * std::sqrt(fConst16)); + fConst21 = 2.0f * (fConst19 / fConst18); + fConst22 = 4.656613e-10f * fConst12; + fConst23 = 1.0f - Wind_faustpower2_f(fConst7); + fConst24 = std::sqrt(std::max(0.0f, fConst23)); + fConst25 = fConst24 / fConst8; + fConst26 = 1.0f - Wind_faustpower2_f(fConst6); + fConst27 = std::sqrt(std::max(0.0f, fConst26)); + fConst28 = std::sqrt(fConst23); + fConst29 = 1.0f - fConst5 / fConst2; + fConst30 = (1.0f - fConst3 - 2.0f * fConst6 * fConst29) / (fConst28 * std::sqrt(fConst26)); + fConst31 = 2.0f * (fConst29 / fConst28); + fConst32 = fConst7 / fConst8; + fConst33 = 0.7f / fConst2; + } + + virtual void instanceResetUserInterface() { + } + + virtual void instanceClear() { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iRec6[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + fRec5[l1] = 0.0f; + } + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + fRec3[l2] = 0.0f; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec2[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + fRec0[l4] = 0.0f; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + fRec13[l5] = 0.0f; + } + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + fRec11[l6] = 0.0f; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + fRec10[l7] = 0.0f; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec8[l8] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual Wind* clone() { + return new Wind(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("untitled"); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + FAUSTFLOAT* output1 = outputs[1]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + int iTemp0 = 1103515245 * (iRec6[1] + 12345); + iRec6[0] = 1103515245 * (iTemp0 + 12345); + int iRec7 = iTemp0; + float fTemp1 = float(iRec6[0]); + float fTemp2 = fConst15 * fTemp1 - fConst12 * fRec3[1]; + fRec5[0] = fConst17 * fTemp2 - fConst11 * fRec5[1]; + fRec3[0] = fConst11 * fTemp2 + fConst17 * fRec5[1]; + float fRec4 = fRec5[0]; + float fTemp3 = fConst22 * fTemp1 + fConst14 * fRec3[1] + fConst21 * fRec3[0] + fConst20 * fRec4; + float fTemp4 = fConst25 * fTemp3 - fConst7 * fRec0[1]; + fRec2[0] = fConst27 * fTemp4 - fConst6 * fRec2[1]; + fRec0[0] = fConst6 * fTemp4 + fConst27 * fRec2[1]; + float fRec1 = fRec2[0]; + output0[i0] = FAUSTFLOAT(fConst33 * (fConst32 * fTemp3 + fConst24 * fRec0[1] + fConst31 * fRec0[0] + fConst30 * fRec1)); + float fTemp5 = float(iRec7); + float fTemp6 = fConst15 * fTemp5 - fConst12 * fRec11[1]; + fRec13[0] = fConst17 * fTemp6 - fConst11 * fRec13[1]; + fRec11[0] = fConst11 * fTemp6 + fConst17 * fRec13[1]; + float fRec12 = fRec13[0]; + float fTemp7 = fConst22 * fTemp5 + fConst14 * fRec11[1] + fConst21 * fRec11[0] + fConst20 * fRec12; + float fTemp8 = fConst25 * fTemp7 - fConst7 * fRec8[1]; + fRec10[0] = fConst27 * fTemp8 - fConst6 * fRec10[1]; + fRec8[0] = fConst6 * fTemp8 + fConst27 * fRec10[1]; + float fRec9 = fRec10[0]; + output1[i0] = FAUSTFLOAT(fConst33 * (fConst32 * fTemp7 + fConst24 * fRec8[1] + fConst31 * fRec8[0] + fConst30 * fRec9)); + iRec6[1] = iRec6[0]; + fRec5[1] = fRec5[0]; + fRec3[1] = fRec3[0]; + fRec2[1] = fRec2[0]; + fRec0[1] = fRec0[0]; + fRec13[1] = fRec13[0]; + fRec11[1] = fRec11[0]; + fRec10[1] = fRec10[0]; + fRec8[1] = fRec8[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/windchimes.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/windchimes.cpp new file mode 100644 index 0000000000..b86ba43f4c --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/Generators/windchimes.cpp @@ -0,0 +1,556 @@ +/* ------------------------------------------------------------ +name: "untitled" +Code generated with Faust 2.79.4 (https://faust.grame.fr) +Compilation options: -lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0 +------------------------------------------------------------ */ + +#ifndef __Windchimes_H__ +#define __Windchimes_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FAUSTCLASS +#define FAUSTCLASS Windchimes +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +#if defined(_WIN32) +#define RESTRICT __restrict +#else +#define RESTRICT __restrict__ +#endif + + +class Windchimes : public dsp { + + private: + + int iVec0[2]; + int iVec1[2]; + int iRec7[2]; + float fRec6[2]; + float fRec5[2]; + int fSampleRate; + float fConst0; + float fConst1; + int iRec8[2]; + float fVec2[2]; + int iRec4[2]; + float fRec3[2]; + float fConst2; + float fRec10[3]; + FAUSTFLOAT fHbargraph0; + FAUSTFLOAT fHbargraph1; + float fRec9[2]; + float fRec11[2]; + float fRec12[2]; + float fRec13[2]; + float fRec14[2]; + float fRec15[2]; + float fRec16[2]; + float fRec2[3]; + int iVec3[2]; + int iRec1[2]; + float fConst3; + float fRec17[2]; + float fRec0[3]; + int iVec4[2]; + int iRec19[2]; + float fRec20[2]; + float fRec18[3]; + int iVec5[2]; + int iRec22[2]; + float fRec23[2]; + float fRec21[3]; + int iVec6[2]; + int iRec25[2]; + float fRec26[2]; + float fRec24[3]; + int iVec7[2]; + int iRec28[2]; + float fRec29[2]; + float fRec27[3]; + float fRec30[3]; + float fRec31[3]; + float fRec32[3]; + float fRec33[3]; + float fRec34[3]; + float fRec35[3]; + float fRec36[3]; + float fRec37[3]; + float fRec38[3]; + float fRec39[3]; + float fRec40[3]; + float fRec41[3]; + float fRec42[3]; + float fRec43[3]; + float fRec44[3]; + float fRec45[3]; + float fRec46[3]; + float fRec47[3]; + float fRec48[3]; + float fRec49[3]; + + public: + Windchimes() { + } + + void metadata(Meta* m) { + m->declare("basics.lib/name", "Faust Basic Element Library"); + m->declare("basics.lib/sAndH:author", "Romain Michon"); + m->declare("basics.lib/selectoutn:author", "Vince"); + m->declare("basics.lib/version", "1.21.0"); + m->declare("compile_options", "-lang cpp -ct 1 -es 1 -mcd 16 -mdd 1024 -mdy 33 -single -ftz 0"); + m->declare("envelopes.lib/ar:author", "Yann Orlarey, Stéphane Letz"); + m->declare("envelopes.lib/author", "GRAME"); + m->declare("envelopes.lib/copyright", "GRAME"); + m->declare("envelopes.lib/license", "LGPL with exception"); + m->declare("envelopes.lib/name", "Faust Envelope Library"); + m->declare("envelopes.lib/version", "1.3.0"); + m->declare("filename", "untitled.dsp"); + m->declare("filters.lib/fir:author", "Julius O. Smith III"); + m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/iir:author", "Julius O. Smith III"); + m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III "); + m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license"); + m->declare("filters.lib/lowpass0_highpass1", "MIT-style STK-4.3 license"); + m->declare("filters.lib/name", "Faust Filters Library"); + m->declare("filters.lib/version", "1.7.1"); + m->declare("maths.lib/author", "GRAME"); + m->declare("maths.lib/copyright", "GRAME"); + m->declare("maths.lib/license", "LGPL with exception"); + m->declare("maths.lib/name", "Faust Math Library"); + m->declare("maths.lib/version", "2.8.1"); + m->declare("name", "untitled"); + m->declare("noises.lib/name", "Faust Noise Generator Library"); + m->declare("noises.lib/version", "1.4.1"); + m->declare("platform.lib/name", "Generic Platform Library"); + m->declare("platform.lib/version", "1.3.0"); + m->declare("routes.lib/name", "Faust Signal Routing Library"); + m->declare("routes.lib/version", "1.2.0"); + m->declare("signals.lib/name", "Faust Signal Routing Library"); + m->declare("signals.lib/version", "1.6.0"); + } + + virtual int getNumInputs() { + return 0; + } + virtual int getNumOutputs() { + return 2; + } + + static void classInit(int sample_rate) { + } + + virtual void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(1.92e+05f, std::max(1.0f, float(fSampleRate))); + fConst1 = 0.001f * fConst0; + fConst2 = 2.0f / fConst0; + fConst3 = 1.0f / std::max(1.0f, 0.02f * fConst0); + } + + virtual void instanceResetUserInterface() { + } + + virtual void instanceClear() { + for (int l0 = 0; l0 < 2; l0 = l0 + 1) { + iVec0[l0] = 0; + } + for (int l1 = 0; l1 < 2; l1 = l1 + 1) { + iVec1[l1] = 0; + } + for (int l2 = 0; l2 < 2; l2 = l2 + 1) { + iRec7[l2] = 0; + } + for (int l3 = 0; l3 < 2; l3 = l3 + 1) { + fRec6[l3] = 0.0f; + } + for (int l4 = 0; l4 < 2; l4 = l4 + 1) { + fRec5[l4] = 0.0f; + } + for (int l5 = 0; l5 < 2; l5 = l5 + 1) { + iRec8[l5] = 0; + } + for (int l6 = 0; l6 < 2; l6 = l6 + 1) { + fVec2[l6] = 0.0f; + } + for (int l7 = 0; l7 < 2; l7 = l7 + 1) { + iRec4[l7] = 0; + } + for (int l8 = 0; l8 < 2; l8 = l8 + 1) { + fRec3[l8] = 0.0f; + } + for (int l9 = 0; l9 < 3; l9 = l9 + 1) { + fRec10[l9] = 0.0f; + } + for (int l10 = 0; l10 < 2; l10 = l10 + 1) { + fRec9[l10] = 0.0f; + } + for (int l11 = 0; l11 < 2; l11 = l11 + 1) { + fRec11[l11] = 0.0f; + } + for (int l12 = 0; l12 < 2; l12 = l12 + 1) { + fRec12[l12] = 0.0f; + } + for (int l13 = 0; l13 < 2; l13 = l13 + 1) { + fRec13[l13] = 0.0f; + } + for (int l14 = 0; l14 < 2; l14 = l14 + 1) { + fRec14[l14] = 0.0f; + } + for (int l15 = 0; l15 < 2; l15 = l15 + 1) { + fRec15[l15] = 0.0f; + } + for (int l16 = 0; l16 < 2; l16 = l16 + 1) { + fRec16[l16] = 0.0f; + } + for (int l17 = 0; l17 < 3; l17 = l17 + 1) { + fRec2[l17] = 0.0f; + } + for (int l18 = 0; l18 < 2; l18 = l18 + 1) { + iVec3[l18] = 0; + } + for (int l19 = 0; l19 < 2; l19 = l19 + 1) { + iRec1[l19] = 0; + } + for (int l20 = 0; l20 < 2; l20 = l20 + 1) { + fRec17[l20] = 0.0f; + } + for (int l21 = 0; l21 < 3; l21 = l21 + 1) { + fRec0[l21] = 0.0f; + } + for (int l22 = 0; l22 < 2; l22 = l22 + 1) { + iVec4[l22] = 0; + } + for (int l23 = 0; l23 < 2; l23 = l23 + 1) { + iRec19[l23] = 0; + } + for (int l24 = 0; l24 < 2; l24 = l24 + 1) { + fRec20[l24] = 0.0f; + } + for (int l25 = 0; l25 < 3; l25 = l25 + 1) { + fRec18[l25] = 0.0f; + } + for (int l26 = 0; l26 < 2; l26 = l26 + 1) { + iVec5[l26] = 0; + } + for (int l27 = 0; l27 < 2; l27 = l27 + 1) { + iRec22[l27] = 0; + } + for (int l28 = 0; l28 < 2; l28 = l28 + 1) { + fRec23[l28] = 0.0f; + } + for (int l29 = 0; l29 < 3; l29 = l29 + 1) { + fRec21[l29] = 0.0f; + } + for (int l30 = 0; l30 < 2; l30 = l30 + 1) { + iVec6[l30] = 0; + } + for (int l31 = 0; l31 < 2; l31 = l31 + 1) { + iRec25[l31] = 0; + } + for (int l32 = 0; l32 < 2; l32 = l32 + 1) { + fRec26[l32] = 0.0f; + } + for (int l33 = 0; l33 < 3; l33 = l33 + 1) { + fRec24[l33] = 0.0f; + } + for (int l34 = 0; l34 < 2; l34 = l34 + 1) { + iVec7[l34] = 0; + } + for (int l35 = 0; l35 < 2; l35 = l35 + 1) { + iRec28[l35] = 0; + } + for (int l36 = 0; l36 < 2; l36 = l36 + 1) { + fRec29[l36] = 0.0f; + } + for (int l37 = 0; l37 < 3; l37 = l37 + 1) { + fRec27[l37] = 0.0f; + } + for (int l38 = 0; l38 < 3; l38 = l38 + 1) { + fRec30[l38] = 0.0f; + } + for (int l39 = 0; l39 < 3; l39 = l39 + 1) { + fRec31[l39] = 0.0f; + } + for (int l40 = 0; l40 < 3; l40 = l40 + 1) { + fRec32[l40] = 0.0f; + } + for (int l41 = 0; l41 < 3; l41 = l41 + 1) { + fRec33[l41] = 0.0f; + } + for (int l42 = 0; l42 < 3; l42 = l42 + 1) { + fRec34[l42] = 0.0f; + } + for (int l43 = 0; l43 < 3; l43 = l43 + 1) { + fRec35[l43] = 0.0f; + } + for (int l44 = 0; l44 < 3; l44 = l44 + 1) { + fRec36[l44] = 0.0f; + } + for (int l45 = 0; l45 < 3; l45 = l45 + 1) { + fRec37[l45] = 0.0f; + } + for (int l46 = 0; l46 < 3; l46 = l46 + 1) { + fRec38[l46] = 0.0f; + } + for (int l47 = 0; l47 < 3; l47 = l47 + 1) { + fRec39[l47] = 0.0f; + } + for (int l48 = 0; l48 < 3; l48 = l48 + 1) { + fRec40[l48] = 0.0f; + } + for (int l49 = 0; l49 < 3; l49 = l49 + 1) { + fRec41[l49] = 0.0f; + } + for (int l50 = 0; l50 < 3; l50 = l50 + 1) { + fRec42[l50] = 0.0f; + } + for (int l51 = 0; l51 < 3; l51 = l51 + 1) { + fRec43[l51] = 0.0f; + } + for (int l52 = 0; l52 < 3; l52 = l52 + 1) { + fRec44[l52] = 0.0f; + } + for (int l53 = 0; l53 < 3; l53 = l53 + 1) { + fRec45[l53] = 0.0f; + } + for (int l54 = 0; l54 < 3; l54 = l54 + 1) { + fRec46[l54] = 0.0f; + } + for (int l55 = 0; l55 < 3; l55 = l55 + 1) { + fRec47[l55] = 0.0f; + } + for (int l56 = 0; l56 < 3; l56 = l56 + 1) { + fRec48[l56] = 0.0f; + } + for (int l57 = 0; l57 < 3; l57 = l57 + 1) { + fRec49[l57] = 0.0f; + } + } + + virtual void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + + virtual void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + virtual Windchimes* clone() { + return new Windchimes(); + } + + virtual int getSampleRate() { + return fSampleRate; + } + + virtual void buildUserInterface(UI* ui_interface) { + ui_interface->openVerticalBox("wind chimes"); + ui_interface->addHorizontalBargraph("energy", &fHbargraph0, FAUSTFLOAT(0.0f), FAUSTFLOAT(1.5f)); + ui_interface->addHorizontalBargraph("hit probability", &fHbargraph1, FAUSTFLOAT(0.0f), FAUSTFLOAT(1.0f)); + ui_interface->closeBox(); + } + + virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) { + FAUSTFLOAT* output0 = outputs[0]; + FAUSTFLOAT* output1 = outputs[1]; + for (int i0 = 0; i0 < count; i0 = i0 + 1) { + iVec0[0] = 1; + int iTemp0 = iRec4[1] + (1 - iVec0[1]); + iVec1[0] = iTemp0; + iRec7[0] = 1103515245 * iRec7[1] + 12345; + float fTemp1 = float(iRec7[0]); + float fTemp2 = 4.656613e-10f * fTemp1; + fRec6[0] = ((iTemp0) ? 1e+01f * (fTemp2 + 1.0f) + 3e+01f : fRec6[1]); + fRec5[0] = ((iTemp0) ? fRec6[0] : fRec5[1]); + float fTemp3 = std::max(1.0f, fConst1 * fRec5[0]); + iRec8[0] = (iRec8[1] + (iRec8[1] > 0)) * (iTemp0 <= iVec1[1]) + (iTemp0 > iVec1[1]); + float fTemp4 = float(iRec8[0]); + float fTemp5 = std::max(0.0f, std::min(fTemp4 / fTemp3, fTemp3 + (1.0f - fTemp4))); + fVec2[0] = fTemp5; + iRec4[0] = (fVec2[1] != 0.0f) & (fTemp5 == 0.0f); + fRec3[0] = ((iRec4[0]) ? fRec2[2] : fRec3[1]); + fRec10[0] = 0.99997f * (fConst2 + fRec10[2]); + fHbargraph0 = FAUSTFLOAT(fRec10[0]); + float fTemp6 = fHbargraph0; + fHbargraph1 = FAUSTFLOAT(1.0f / (99.0f * std::exp(-(2.0f * fTemp6)) + 1.0f)); + fRec9[0] = ((iRec4[0]) ? fHbargraph1 : fRec9[1]); + float fTemp7 = std::fabs(fTemp2); + fRec11[0] = ((iRec4[0] * (fRec3[0] == 0.0f)) ? fTemp7 : fRec11[1]); + float fTemp8 = 0.5f * fRec9[0]; + fRec12[0] = ((iRec4[0] * (fRec3[0] == 1.0f)) ? fTemp7 : fRec12[1]); + fRec13[0] = ((iRec4[0] * (fRec3[0] == 2.0f)) ? fTemp7 : fRec13[1]); + fRec14[0] = ((iRec4[0] * (fRec3[0] == 3.0f)) ? fTemp7 : fRec14[1]); + fRec15[0] = ((iRec4[0] * (fRec3[0] == 4.0f)) ? fTemp7 : fRec15[1]); + fRec16[0] = ((iRec4[0] * (fRec3[0] == 5.0f)) ? fTemp7 : fRec16[1]); + fRec2[0] = ((fRec3[0] >= 3.0f) ? float(((fRec3[0] >= 5.0f) ? ((fRec16[0] <= fTemp8) ? 1 : ((fRec16[0] <= fRec9[0]) ? 4 : 0)) : ((fRec3[0] >= 4.0f) ? ((fRec15[0] <= fTemp8) ? 5 : ((fRec15[0] <= fRec9[0]) ? 3 : 0)) : ((fRec14[0] <= fTemp8) ? 4 : ((fRec14[0] <= fRec9[0]) ? 2 : 0))))) : ((fRec3[0] >= 2.0f) ? float(((fRec13[0] <= fTemp8) ? 3 : ((fRec13[0] <= fRec9[0]) ? 1 : 0))) : ((fRec3[0] >= 1.0f) ? float(((fRec12[0] <= fTemp8) ? 2 : ((fRec12[0] <= fRec9[0]) ? 5 : 0))) : ((fRec11[0] <= fRec9[0]) ? std::round(4.0f * (fRec11[0] / fRec9[0])) + 1.0f : 0.0f)))); + int iTemp9 = fRec2[0] != fRec2[1]; + int iTemp10 = (fRec2[0] == 5.0f) * iTemp9; + iVec3[0] = iTemp10; + iRec1[0] = (iRec1[1] + (iRec1[1] > 0)) * (iTemp10 <= iVec3[1]) + (iTemp10 > iVec3[1]); + float fTemp11 = float(iRec1[0]); + fRec17[0] = ((iTemp10) ? fTemp6 : fRec17[1]); + float fTemp12 = 4.656613e-10f * std::sqrt(fRec17[0] + 0.1f) * fTemp1 * std::pow(0.97f, 1e+03f * (1.0f - std::max(0.0f, std::min(fTemp11, fConst3 * (1.0f - fTemp11) + 1.0f)))); + fRec0[0] = fTemp12 + 1.9976895f * fRec0[1] - 0.99998564f * fRec0[2]; + int iTemp13 = (fRec2[0] == 4.0f) * iTemp9; + iVec4[0] = iTemp13; + iRec19[0] = (iRec19[1] + (iRec19[1] > 0)) * (iTemp13 <= iVec4[1]) + (iTemp13 > iVec4[1]); + float fTemp14 = float(iRec19[0]); + fRec20[0] = ((iTemp13) ? fTemp6 : fRec20[1]); + float fTemp15 = 4.656613e-10f * std::sqrt(fRec20[0] + 0.1f) * fTemp1 * std::pow(0.97f, 1e+03f * (1.0f - std::max(0.0f, std::min(fTemp14, fConst3 * (1.0f - fTemp14) + 1.0f)))); + fRec18[0] = fTemp15 + 1.9981018f * fRec18[1] - 0.99998564f * fRec18[2]; + int iTemp16 = (fRec2[0] == 3.0f) * iTemp9; + iVec5[0] = iTemp16; + iRec22[0] = (iRec22[1] + (iRec22[1] > 0)) * (iTemp16 <= iVec5[1]) + (iTemp16 > iVec5[1]); + float fTemp17 = float(iRec22[0]); + fRec23[0] = ((iTemp16) ? fTemp6 : fRec23[1]); + float fTemp18 = 4.656613e-10f * std::sqrt(fRec23[0] + 0.1f) * fTemp1 * std::pow(0.97f, 1e+03f * (1.0f - std::max(0.0f, std::min(fTemp17, fConst3 * (1.0f - fTemp17) + 1.0f)))); + fRec21[0] = fTemp18 + 1.9985057f * fRec21[1] - 0.99998564f * fRec21[2]; + int iTemp19 = (fRec2[0] == 2.0f) * iTemp9; + iVec6[0] = iTemp19; + iRec25[0] = (iRec25[1] + (iRec25[1] > 0)) * (iTemp19 <= iVec6[1]) + (iTemp19 > iVec6[1]); + float fTemp20 = float(iRec25[0]); + fRec26[0] = ((iTemp19) ? fTemp6 : fRec26[1]); + float fTemp21 = 4.656613e-10f * std::sqrt(fRec26[0] + 0.1f) * fTemp1 * std::pow(0.97f, 1e+03f * (1.0f - std::max(0.0f, std::min(fTemp20, fConst3 * (1.0f - fTemp20) + 1.0f)))); + fRec24[0] = fTemp21 + 1.9989505f * fRec24[1] - 0.99998564f * fRec24[2]; + int iTemp22 = (fRec2[0] == 1.0f) * iTemp9; + iVec7[0] = iTemp22; + iRec28[0] = (iRec28[1] + (iRec28[1] > 0)) * (iTemp22 <= iVec7[1]) + (iTemp22 > iVec7[1]); + float fTemp23 = float(iRec28[0]); + fRec29[0] = ((iTemp22) ? fTemp6 : fRec29[1]); + float fTemp24 = 4.656613e-10f * std::sqrt(fRec29[0] + 0.1f) * fTemp1 * std::pow(0.97f, 1e+03f * (1.0f - std::max(0.0f, std::min(fTemp23, fConst3 * (1.0f - fTemp23) + 1.0f)))); + fRec27[0] = fTemp24 + 1.8915979f * fRec27[1] - 0.9988494f * fRec27[2]; + fRec30[0] = fTemp24 + 1.9462262f * fRec30[1] - 0.9994245f * fRec30[2]; + fRec31[0] = fTemp24 + 1.9784355f * fRec31[1] - 0.9997122f * fRec31[2]; + fRec32[0] = fTemp24 + 1.9939524f * fRec32[1] - 0.99991775f * fRec32[2]; + fRec33[0] = fTemp24 + 1.9991579f * fRec33[1] - 0.99998564f * fRec33[2]; + fRec34[0] = fTemp21 + 1.992513f * fRec34[1] - 0.99991775f * fRec34[2]; + fRec35[0] = fTemp21 + 1.9734613f * fRec35[1] - 0.9997122f * fRec35[2]; + fRec36[0] = fTemp21 + 1.9342905f * fRec36[1] - 0.9994245f * fRec36[2]; + fRec37[0] = fTemp21 + 1.8685968f * fRec37[1] - 0.9988494f * fRec37[2]; + fRec38[0] = fTemp18 + 1.9894383f * fRec38[1] - 0.99991775f * fRec38[2]; + fRec39[0] = fTemp18 + 1.963045f * fRec39[1] - 0.9997122f * fRec39[2]; + fRec40[0] = fTemp18 + 1.9085721f * fRec40[1] - 0.9994245f * fRec40[2]; + fRec41[0] = fTemp18 + 1.8175561f * fRec41[1] - 0.9988494f * fRec41[2]; + fRec42[0] = fTemp15 + 1.9867989f * fRec42[1] - 0.99991775f * fRec42[2]; + fRec43[0] = fTemp15 + 1.9541994f * fRec43[1] - 0.9997122f * fRec43[2]; + fRec44[0] = fTemp15 + 1.8867846f * fRec44[1] - 0.9994245f * fRec44[2]; + fRec45[0] = fTemp15 + 1.7745043f * fRec45[1] - 0.9988494f * fRec45[2]; + fRec46[0] = fTemp12 + 1.9839008f * fRec46[1] - 0.99991775f * fRec46[2]; + fRec47[0] = fTemp12 + 1.9448138f * fRec47[1] - 0.9997122f * fRec47[2]; + fRec48[0] = fTemp12 + 1.8637005f * fRec48[1] - 0.9994245f * fRec48[2]; + fRec49[0] = fTemp12 + 1.729075f * fRec49[1] - 0.9988494f * fRec49[2]; + float fTemp25 = 0.25f * (0.027578233f * (fRec49[0] - fRec49[2]) + 0.00984774f * (fRec48[0] - fRec48[2]) + 0.46534723f * (fRec47[0] - fRec47[2]) + 0.046706475f * (fRec46[0] - fRec46[2]) + 0.025301978f * (fRec45[0] - fRec45[2]) + 0.008998045f * (fRec44[0] - fRec44[2]) + 0.42420912f * (fRec43[0] - fRec43[2]) + 0.04228563f * (fRec42[0] - fRec42[2]) + 0.02287444f * (fRec41[0] - fRec41[2]) + 0.008103716f * (fRec40[0] - fRec40[2]) + 0.3811863f * (fRec39[0] - fRec39[2]) + 0.03780568f * (fRec38[0] - fRec38[2]) + 0.0195181f * (fRec37[0] - fRec37[2]) + 0.006884051f * (fRec36[0] - fRec36[2]) + 0.3229546f * (fRec35[0] - fRec35[2]) + 0.03179165f * (fRec34[0] - fRec34[2]) + 0.004528017f * (fRec33[0] - fRec33[2]) + 0.028540056f * (fRec32[0] - fRec32[2]) + 0.29093292f * (fRec31[0] - fRec31[2]) + 0.0062308447f * (fRec30[0] - fRec30[2]) + 0.017763702f * (fRec27[0] - fRec27[2]) + 0.005063458f * (fRec24[0] - fRec24[2]) + 0.0060538645f * (fRec21[0] - fRec21[2]) + 0.0068299635f * (fRec18[0] - fRec18[2]) + 0.007540041f * (fRec0[0] - fRec0[2])); + output0[i0] = FAUSTFLOAT(fTemp25); + output1[i0] = FAUSTFLOAT(fTemp25); + iVec0[1] = iVec0[0]; + iVec1[1] = iVec1[0]; + iRec7[1] = iRec7[0]; + fRec6[1] = fRec6[0]; + fRec5[1] = fRec5[0]; + iRec8[1] = iRec8[0]; + fVec2[1] = fVec2[0]; + iRec4[1] = iRec4[0]; + fRec3[1] = fRec3[0]; + fRec10[2] = fRec10[1]; + fRec10[1] = fRec10[0]; + fRec9[1] = fRec9[0]; + fRec11[1] = fRec11[0]; + fRec12[1] = fRec12[0]; + fRec13[1] = fRec13[0]; + fRec14[1] = fRec14[0]; + fRec15[1] = fRec15[0]; + fRec16[1] = fRec16[0]; + fRec2[2] = fRec2[1]; + fRec2[1] = fRec2[0]; + iVec3[1] = iVec3[0]; + iRec1[1] = iRec1[0]; + fRec17[1] = fRec17[0]; + fRec0[2] = fRec0[1]; + fRec0[1] = fRec0[0]; + iVec4[1] = iVec4[0]; + iRec19[1] = iRec19[0]; + fRec20[1] = fRec20[0]; + fRec18[2] = fRec18[1]; + fRec18[1] = fRec18[0]; + iVec5[1] = iVec5[0]; + iRec22[1] = iRec22[0]; + fRec23[1] = fRec23[0]; + fRec21[2] = fRec21[1]; + fRec21[1] = fRec21[0]; + iVec6[1] = iVec6[0]; + iRec25[1] = iRec25[0]; + fRec26[1] = fRec26[0]; + fRec24[2] = fRec24[1]; + fRec24[1] = fRec24[0]; + iVec7[1] = iVec7[0]; + iRec28[1] = iRec28[0]; + fRec29[1] = fRec29[0]; + fRec27[2] = fRec27[1]; + fRec27[1] = fRec27[0]; + fRec30[2] = fRec30[1]; + fRec30[1] = fRec30[0]; + fRec31[2] = fRec31[1]; + fRec31[1] = fRec31[0]; + fRec32[2] = fRec32[1]; + fRec32[1] = fRec32[0]; + fRec33[2] = fRec33[1]; + fRec33[1] = fRec33[0]; + fRec34[2] = fRec34[1]; + fRec34[1] = fRec34[0]; + fRec35[2] = fRec35[1]; + fRec35[1] = fRec35[0]; + fRec36[2] = fRec36[1]; + fRec36[1] = fRec36[0]; + fRec37[2] = fRec37[1]; + fRec37[1] = fRec37[0]; + fRec38[2] = fRec38[1]; + fRec38[1] = fRec38[0]; + fRec39[2] = fRec39[1]; + fRec39[1] = fRec39[0]; + fRec40[2] = fRec40[1]; + fRec40[1] = fRec40[0]; + fRec41[2] = fRec41[1]; + fRec41[1] = fRec41[0]; + fRec42[2] = fRec42[1]; + fRec42[1] = fRec42[0]; + fRec43[2] = fRec43[1]; + fRec43[1] = fRec43[0]; + fRec44[2] = fRec44[1]; + fRec44[1] = fRec44[0]; + fRec45[2] = fRec45[1]; + fRec45[1] = fRec45[0]; + fRec46[2] = fRec46[1]; + fRec46[1] = fRec46[0]; + fRec47[2] = fRec47[1]; + fRec47[1] = fRec47[0]; + fRec48[2] = fRec48[1]; + fRec48[1] = fRec48[0]; + fRec49[2] = fRec49[1]; + fRec49[1] = fRec49[0]; + } + } + +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.cpp new file mode 100644 index 0000000000..2ed3a10268 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.cpp @@ -0,0 +1,22 @@ +#include "audio_inputs.h" + +namespace AudioInputs +{ + audioInputList getAudioInputList() + { + audioInputList myAudioInputList; + int ctr = 0; + #define X(ClassName, label) myAudioInputList.emplace_back(ctr++, label); + AUDIO_INPUT_LIST + #undef X + return myAudioInputList; + } + + dsp* createAudioInputById(int id) + { + int ctr = 0; + #define X(ClassName, label) if (id == ctr++) return new ClassName(); + AUDIO_INPUT_LIST + #undef X + } +} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.h new file mode 100644 index 0000000000..420b998c1f --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/AudioInput/audio_inputs.h @@ -0,0 +1,48 @@ +/******************************************************************************* +This header file defines the structure for managing different audio input +generators for a DSP effects. +The file includes the declaration of available audio inputs and provides the +mechanism to retrieve and create these audio inputs by ID. +The list of available audio inputs is defined using macros, and each input +corresponds to a specific audio generator or effect (e.g., Sine wave, Wind, +Rain, etc.). +*******************************************************************************/ + +#ifndef AUDIO_INPUTS_H +#define AUDIO_INPUTS_H + +#include "Generators/sine440.cpp" +#include "Generators/wind.cpp" +#include "Generators/complexRain.cpp" +#include "Generators/fmSynthAnalog.cpp" +#include "Generators/insects.cpp" +#include "Generators/windchimes.cpp" +#include "Generators/waveSynthAnalog.cpp" + +#define AUDIO_INPUT_LIST \ + X(Sine440, L"Sine wave (440Hz)") \ + X(Wind, L"Wind") \ + X(ComplexRain, L"Complex Rain") \ + X(FMSynthAnalog, L"FMSynthAnalog") \ + X(Insects, L"Insects") \ + X(WaveSynthAnalog, L"WaveSynthAnalog") \ + X(Windchimes, L"Windchimes") + +#define DEFAUT_AUDIO_INPUT_FOR_EFFECTS 0 + +#include +#include +#include + +typedef std::vector> audioInputList; + +namespace AudioInputs{ + + /* Function to retrieve the full list of available audio inputs, typically returning an audioInputList.*/ + audioInputList getAudioInputList(); + + /* Function that returns a new dsp instance. The caller is responsible for destroying the dsp object on time. */ + dsp* createAudioInputById(int id); +} + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.cpp new file mode 100644 index 0000000000..bf26abf2cb --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.cpp @@ -0,0 +1,200 @@ +#include "wrapper.h" +#include +#include + +InterpreterWrapper::InterpreterWrapper() + : factory(nullptr) + , mdsp(nullptr) + , mapui(nullptr) +{} + +InterpreterWrapper::~InterpreterWrapper() +{ + reset(); +} + +void InterpreterWrapper::reset() +{ + if (mapui) + { + delete mapui; + mapui = nullptr; + } + + if (mdsp) + { + delete mdsp; + mdsp = nullptr; + } + + if (factory) + { + deleteInterpreterDSPFactory(factory); + factory = nullptr; + } +} + +bool InterpreterWrapper::compileDSP(const std::string dspCode, const PluginConfiguration &cfg, std::string& errorMessage) +{ + + if(factory){ + deleteInterpreterDSPFactory(factory); + factory = nullptr; + } + + std::vector args { + "-I", cfg.path.faust_dspdir.c_str(), + }; + int argc = args.size(); + const char** argv = args.data(); + + factory = createInterpreterDSPFactoryFromString( + cfg.name_app, + dspCode, + argc, + argv, + errorMessage + ); + + if (!factory) + { + std::cerr << "Faust compilation failed : " << errorMessage << std::endl; + return false; + } + + // update shaKey + currentSHA = factory->getSHAKey(); + return true; +} + +bool InterpreterWrapper::createDSPandUI() +{ + mdsp = factory->createDSPInstance(); + if (!mdsp) { + std::cerr << "Cannot create instance " << std::endl; + return false; + } + + mapui = new myMapUI(); + if (!mapui) + { + std::cerr<<" Cannot create mapui "<buildUserInterface(mapui); + mapui->fillShortNames(); + setPluginConfiguration(cfg); + setParameterList(parameters, cfg); + return true; // TODO change return? +} + +void InterpreterWrapper::setupDSP(int sampleRate) +{ + mdsp->init(sampleRate); +} + +FAUSTFLOAT InterpreterWrapper::getParameter(const std::string& name) +{ + return mapui->getParamValue(name); +} + +void InterpreterWrapper::setPluginConfiguration(PluginConfiguration &cfg) +{ + // Extract inputs/outputs + cfg.num_inputs = mdsp->getNumInputs(); + cfg.num_outputs = mdsp->getNumOutputs(); + + // Determine plugin type based on inputs + if (cfg.num_inputs > 0) { + cfg.plugin_type = "effect"; + } else { + cfg.plugin_type = "source"; + } + + // Extract project name & override in case it is provided as a declaration in faust dsp file + // i.e. declare name "Name" + std::string pluginName = factory->getName(); // in case a declare name "name" is assigned by the user, otherwise cfg.app_name. + cfg.plugin_name = PluginUtils::ensure_valid_plugin_name(pluginName); + std::cout << "PLUGIN_NAME changed to " << cfg.plugin_name << std::endl; + + // @TODO: author name? description? + cfg.author = "Unknown"; + cfg.description = "No description provided"; +} + +void InterpreterWrapper::setParameterList(ParameterList& parameters, PluginConfiguration& cfg) +{ + + const int numParams = mapui->getParamsCount(); + parameters.resize(numParams); + + for (const auto& control : mapui->controls) + { + myMapUI::itemInfo item = control.second; + Parameter param; + param.type = item.type; + param.label = item.label; + param.shortname = item.shortname; + param.index = item.index; + param.init = item.init; + param.pmin = item.fmin; + param.pmax = item.fmax; + param.step = item.step; + param.value.store(item.init); + + parameters[item.index] = std::move(param); + } +} + +void InterpreterWrapper::callback(int bufferSize, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) +{ + mdsp->compute(bufferSize, inputs, outputs); +} + +bool InterpreterWrapper::exportCPP( + const std::string& faust_dspdir, + const std::string &filename, + const std::string& dspCode, + const std::string& filepath, + bool doublePrecision, + std::string& errorMessage) +{ + + interpreter_dsp_factory* fct; + + std::vector args { + "-I", faust_dspdir.c_str(), + "-lang", "cpp", + "-json" + }; + if (doublePrecision) + args.push_back("-double"); + int argc = args.size(); + const char** argv = args.data(); + + fct = createInterpreterDSPFactoryFromString( + filename, + dspCode, + argc, + argv, + errorMessage + ); + + if (!fct) + { + std::cerr << "Faust compilation failed : " << errorMessage << std::endl; + return false; + } + + writeInterpreterDSPFactoryToBitcodeFile(fct, filepath); + + deleteInterpreterDSPFactory(fct); + + return true; +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.h new file mode 100644 index 0000000000..67f106249d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Interpreter/wrapper.h @@ -0,0 +1,65 @@ +#ifndef FAUST_INTERPRETER_WRAPPER_H +#define FAUST_INTERPRETER_WRAPPER_H + +#include "faust/dsp/interpreter-dsp.h" +#include "PluginInfo/plugin_config.h" +#include "PluginUtils/plugin_utils.h" +#include "Parameters/myMapUI.h" +#include "Parameters/parameter.h" +#include +#include +#include + +class InterpreterWrapper { + +public: + /* class constructor */ + InterpreterWrapper(); + + /* class destructor */ + ~InterpreterWrapper(); + + /* function used to reset the object to a null state, where mdsp, mapui and factory are all null pointers. */ + void reset(); + + /* function used to compile dsp input using the faust interpreter. */ + bool compileDSP(const std::string dspCode, const PluginConfiguration& cfg, std::string& errorMessage); + + /* function used to initialize mdsp and mapui after the dsp code is compiled.*/ + bool createDSPandUI(); + + /* configures the plugin creation on many different steps, including UI initialization, + * establishing the plugin configuration (i.e. setting num I/O, plugin type, name of plugin etc.). */ + bool configurePlugin(PluginConfiguration&, ParameterList&); + + /* function used to set the sample rate variable to the plugin. */ + void setupDSP(int); + + /* audio callback function */ + void callback(int, FAUSTFLOAT**, FAUSTFLOAT**); + + /* function used to set a parameter's value, by using its name. */ + template + void setParameter(const std::string name, T value) + { + mapui->setParamValue(name, static_cast(value)); + } + + /* function used to get a parameter's value, by using its name. */ + FAUSTFLOAT getParameter(const std::string& name); + + /* Compiles dsp code and store its cpp output into a file on disk. */ + bool exportCPP(const std::string& faust_dspdir, const std::string &filename, const std::string& dspCode, const std::string& filepath, bool doublePrecision, std::string& errorMessage); + +private: + + interpreter_dsp_factory* factory; + dsp* mdsp; + myMapUI* mapui; + std::string currentSHA; + + void setPluginConfiguration(PluginConfiguration&); + void setParameterList(ParameterList&, PluginConfiguration&); +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.cpp new file mode 100644 index 0000000000..61c07343bc --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.cpp @@ -0,0 +1,90 @@ +#include "myMapUI.h" + +myMapUI::~myMapUI() +{ + resetStaticCounter(); +} + + +void myMapUI::fillShortNames() +{ + for (const auto& it : fShortnameZoneMap) { + const auto& shortName = it.first; + const FAUSTFLOAT* zone = it.second; + + auto iter = controls.find(zone); // only access existing item + if (iter != controls.end()) { + iter->second.shortname = shortName; // assign shortname + } + } +} + +void myMapUI::addParameter(FAUSTFLOAT* zone, std::string type, const char* label, int index, double init, double fmin, double fmax, double step) +{ + itemInfo item(type, std::string(label), index, init, fmin, fmax, step); + controls.emplace(zone, std::move(item)); +} + +void myMapUI::resetStaticCounter() +{ + ctr = 0; +} + +void myMapUI::clearParameters() +{ + controls.clear(); + fLabelZoneMap.clear(); + fShortnameZoneMap.clear(); + fPathZoneMap.clear(); + resetStaticCounter(); +} + + // -- active widgets +void myMapUI::addButton(const char* label, FAUSTFLOAT* zone) +{ + MapUI::addZoneLabel(label, zone); + addParameter(zone, "button", label, ctr++); +} + +void myMapUI::addCheckButton(const char* label, FAUSTFLOAT* zone) +{ + addZoneLabel(label, zone); + addParameter(zone, "checkbox", label, ctr++); +} + +void myMapUI::addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step) +{ + addZoneLabel(label, zone); + addParameter(zone, "slider", label, ctr++, init, fmin, fmax, step); +} + +void myMapUI::addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step) +{ + addZoneLabel(label, zone); + addParameter(zone, "slider", label, ctr++, init, fmin, fmax, step); +} + +void myMapUI::addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step) +{ + addZoneLabel(label, zone); + addParameter(zone, "slider", label, ctr++, init, fmin, fmax, step); +} + + // -- passive widgets +void myMapUI::addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax) +{ + addZoneLabel(label, zone); + addParameter(zone, "bargraph", label, ctr++, -DBL_MAX, fmin, fmax, -DBL_MAX); +} + +void myMapUI::addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax) +{ + addZoneLabel(label, zone); + addParameter(zone, "bargraph", label, ctr++, -DBL_MAX, fmin, fmax, -DBL_MAX); +} + +// -- soundfiles +// virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {} + +// -- metadata declarations +// virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val){} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.h new file mode 100644 index 0000000000..65875cdd5b --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/myMapUI.h @@ -0,0 +1,68 @@ +#ifndef MY_MAPUI_H +#define MY_MAPUI_H + +#include +#include "parameter.h" +#include + +// static counter to increment for each new parameter. Has to be reset on each reseting. +static int ctr{0}; + +struct myMapUI : public MapUI +{ + struct itemInfo { + std::string type; + std::string label; + std::string shortname; + int index; + double init; + double fmin; + double fmax; + double step; + + itemInfo(std::string t, std::string l, int idx, double i, double mn, double mx, double s) + :type(t), label(l), index(idx), init(i), fmin(mn), fmax(mx), step(s) + {} + }; + + // controls are a map of (zone ptrs, itemInfo) pairs. + std::unordered_map controls; + + ~myMapUI(); + + /* function that make use of fShortnameZoneMap to fill in the contros the shortName of each param. */ + void fillShortNames(); + + // function that moves a new parameter into the controls structure. + void addParameter(FAUSTFLOAT* zone, std::string type, const char* label, int index, double init = -DBL_MAX, double fmin = -DBL_MAX, double fmax = -DBL_MAX, double step = -DBL_MAX); + + // function to reset the static counter that counts the num of params. + void resetStaticCounter(); + + /* function that clears all the internal structures, and resets the static counter. */ + void clearParameters(); + + // -- active widgets + void addButton(const char* label, FAUSTFLOAT* zone); + + void addCheckButton(const char* label, FAUSTFLOAT* zone); + + void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step); + + void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step); + + void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step); + + // -- passive widgets + void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax); + + void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax); + + // -- soundfiles + // virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone); + + // -- metadata declarations + // virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val); +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.cpp new file mode 100644 index 0000000000..c9bf6cc714 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.cpp @@ -0,0 +1,45 @@ +#include "parameter.h" + +Parameter::Parameter() + : type("") + , label("") + , shortname("") + , index(-1) + , init(0.0) + , pmin(0.0) + , pmax(1.0) + , step(0.01) + , value {0.0f} +{ + preview.id = -1; +} + + + Parameter::Parameter(Parameter&& p) noexcept + : type(p.type) + , label(p.label) + , shortname(p.shortname) + , index(p.index) + , init(p.init) + , pmin (p.pmin) + , pmax (p.pmax) + , step (p.step) + , value{p.value.load()} +{ + preview.id = p.preview.id; +} + +Parameter& Parameter::operator=(Parameter&& p) noexcept +{ + type = std::move(p.type); + label = std::move(p.label); + shortname = std::move(p.shortname); + index = p.index; + init = p.init; + pmin = p.pmin; + pmax = p.pmax; + step = p.step; + value.store(p.value.load()); + preview.id = p.preview.id; + return *this; +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.h new file mode 100644 index 0000000000..3495ea1a0b --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/Parameters/parameter.h @@ -0,0 +1,45 @@ +#ifndef PARAMETERS_H +#define PARAMETERS_H + +#include +#include +#include +#include + +// typedef std::vector> param_meta_items; +struct Parameter; +typedef std::vector ParameterList; + +struct Parameter{ + + std::atomic value{0.0f}; // runtime value of the parameter + + std::string type; + std::string label; + std::string shortname; + int index; + float init; + float pmin; + float pmax; + float step; + // param_meta_items meta; + + struct UI + { + int id; + }preview; + + // constructor + Parameter(); + + // delete copying + Parameter(const Parameter &p) = delete; + Parameter &operator=(const Parameter &p) = delete; + + // support move + Parameter(Parameter&& p) noexcept; + Parameter& operator=(Parameter&& p) noexcept; + +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_config.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_config.h new file mode 100644 index 0000000000..87a804773a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_config.h @@ -0,0 +1,56 @@ +#ifndef PLUGIN_CONFIG_H +#define PLUGIN_CONFIG_H + +#define STORAGE_DIRNAME "_faust" +#define DEFAULT_NAME_APP "Faust Interpreter Plugin" + +#define PREVIEW_WINDOW_WIDTH 640 +#define PREVIEW_WINDOW_HEIGHT 480 + +#include + +struct PluginConfiguration { + + std::string name_app {std::string(DEFAULT_NAME_APP)}; + + struct Paths { + std::string wwiseRoot; + std::string exportPath; + std::string faust_includedir; + std::string faust_dspdir; + std::string archfile; + std::string config = "Debug"; + }path; + + std::string plugin_type; + std::string plugin_name; + std::string author; + std::string description; + int num_inputs = 0; + int num_outputs = 0; + + int sampleRate=0; + int bufferSize=0; + int speakersAvail=0; + int maxSpeakersAvail=0; + + struct PreviewWindow { + int width = int(PREVIEW_WINDOW_WIDTH); + int height = int (PREVIEW_WINDOW_HEIGHT); + }preview; + + void reset() + { + name_app=std::string(DEFAULT_NAME_APP); + plugin_type=""; + plugin_name=""; + author=""; + description=""; + num_inputs = 0; + num_outputs = 0; + sampleRate=0; + speakersAvail = (maxSpeakersAvail != 0) ? maxSpeakersAvail : 0; + } +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_state.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_state.h new file mode 100644 index 0000000000..b7cc30c70d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginInfo/plugin_state.h @@ -0,0 +1,22 @@ +#ifndef PLUGIN_STATE_H +#define PLUGIN_STATE_H + +enum PluginState{ + ZERO_STATE, + // IDDLE, // for when loading previously compiled plugins? i.e. when opening wwise? + PENDING_CREATION, + ERR_COMPILE_DSP, + DSP_COMPILED, + ERR_DSPUI_CREATION, + DSPUI_CREATED, + PENDING_CONFIGURATION, + ERR_CONFIGURE_PLUGIN, + PLUGIN_CONFIGURED, + PLUGIN_SET, + BUILT, + READY, + RESET, + DESTROY +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.cpp new file mode 100644 index 0000000000..9b26b3e12a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.cpp @@ -0,0 +1,86 @@ +#include "EffectPlugin.h" +#include "AudioInput/audio_inputs.h" + +WwiseEffectPlugin::WwiseEffectPlugin( + PluginConfiguration& config, + ParameterList& params, + InterpreterWrapper& interpreter +) + : AbstractPlugin(config, params, interpreter) + , audioSource(nullptr) +{} + +WwiseEffectPlugin::~WwiseEffectPlugin() +{ + if (audioSource) + { + delete audioSource; + audioSource = nullptr; + } +} + +void WwiseEffectPlugin::reset() +{ + AbstractPlugin::reset(); + faust_inputs.clear(); + silenceBuffers.clear(); + delete audioSource; + audioSource = nullptr; +} + +void WwiseEffectPlugin::setup() +{ + AbstractPlugin::setup(); + faust_inputs.resize(cfg.num_inputs); +} + +void WwiseEffectPlugin::setAudioInput(int audioInputID) +{ + audioSource = AudioInputs::createAudioInputById(audioInputID); +} + +void WwiseEffectPlugin::setSampleRate(int SR) +{ + audioSource->init(SR); +} + +void WwiseEffectPlugin::callback(std::vector& outputs, const AkUInt32 bufferSize) +{ + setParameters(); + + for (AkUInt32 ch = 0; ch < cfg.num_outputs; ++ch) + { + faust_outputs[ch] = outputs[ch]; + } + + preprocessInputChannels(bufferSize); + + // fill the input. The input to the plugin is the output of the audioSource. + audioSource->compute(bufferSize,nullptr,faust_inputs.data()); + + faustInterpreter.callback(bufferSize, faust_inputs.data(), faust_outputs.data()); + +} + +void WwiseEffectPlugin::preprocessInputChannels(const AkUInt32 bufferSize) +{ + // Runs only once initializing the faust_inputs with silence + // .. and resizing them to the max size between audio gen and effect plugin... + + if (silenceBuffers.empty()){ + + int numChannelsEffect = cfg.num_inputs; + int numChannelsGenerator = audioSource->getNumOutputs(); + int maxChannels = (numChannelsEffect >= numChannelsGenerator) ? numChannelsEffect : numChannelsGenerator; + + if (maxChannels != numChannelsEffect) + faust_inputs.resize(maxChannels); + silenceBuffers.resize(maxChannels); + + for (int ch = 0; ch < maxChannels ; ++ch) + { + silenceBuffers[ch].resize(bufferSize, 0.0f); + faust_inputs[ch] = silenceBuffers[ch].data(); + } + } +} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.h new file mode 100644 index 0000000000..a36b1de0aa --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/EffectPlugin.h @@ -0,0 +1,24 @@ +#ifndef TEMPLATE_EFFECT_PLUGIN_H +#define TEMPLATE_EFFECT_PLUGIN_H + +#include "abstract.h" + +class WwiseEffectPlugin: public AbstractPlugin +{ +public: + WwiseEffectPlugin(PluginConfiguration&, ParameterList&, InterpreterWrapper&); + ~WwiseEffectPlugin() override final; + void reset() override final; + void setup() override final; + void callback(std::vector&, const AkUInt32) override final; + //sets an audio input given its ID. + void setAudioInput(int); + void setSampleRate(int); +private: + std::vector faust_inputs; + std::vector> silenceBuffers; + dsp* audioSource; + void preprocessInputChannels(const AkUInt32); +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.cpp new file mode 100644 index 0000000000..728f0fe3a1 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.cpp @@ -0,0 +1,35 @@ +#include "SourcePlugin.h" + +WwiseSourcePlugin::WwiseSourcePlugin +( + PluginConfiguration& config, + ParameterList& params, + InterpreterWrapper& interpreter +) + : AbstractPlugin(config, params, interpreter) +{} + +void WwiseSourcePlugin::reset() +{ + AbstractPlugin::reset(); +} + +void WwiseSourcePlugin::setup() +{ + AbstractPlugin::setup(); +} + +void WwiseSourcePlugin::callback(std::vector& outputs, const AkUInt32 bufferSize) +{ + + setParameters(); + + for (AkUInt32 ch = 0; ch < cfg.num_outputs; ++ch) + { + faust_outputs[ch] = outputs[ch]; + } + + faustInterpreter.callback(bufferSize, nullptr, faust_outputs.data()); + + +} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.h new file mode 100644 index 0000000000..20f3dd6952 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/SourcePlugin.h @@ -0,0 +1,16 @@ +#ifndef TEMPLATE_SOURCE_PLUGIN_H +#define TEMPLATE_SOURCE_PLUGIN_H + +#include "abstract.h" + +class WwiseSourcePlugin: public AbstractPlugin +{ +public: + WwiseSourcePlugin(PluginConfiguration&, ParameterList&, InterpreterWrapper&); + ~WwiseSourcePlugin() = default; + void reset() override final; + void setup() override final; + void callback(std::vector&, const AkUInt32) override final; +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.cpp new file mode 100644 index 0000000000..7deb2edcd4 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.cpp @@ -0,0 +1,441 @@ +#include "plugin_window.h" +#include "PluginUtils/plugin_utils.h" +#include + +#define PREVIEW_ID_BASE 1000 + +PluginWindow::PluginWindow(HWND parent, PluginConfiguration& config, ParameterList& params) + : cfg(config) + , parameters(params) + , parentWnd(parent) + , windowCreated(false) + , y_span {DEFAULT_Y_SPAN} + , x_margin{DEFAULT_X_MARGIN} + , curr_height(10) + , windowTitle(PluginUtils::string2wstring(cfg.plugin_name).c_str()) + +{ + windowCreated = createWindow(); +} + +PluginWindow::~PluginWindow() +{ + Close(); +} + +void PluginWindow::Close() +{ + if (hwnd) + { + DestroyWindow(hwnd); + hwnd = nullptr; + } + sliderValues.clear(); + monitorValues.clear(); +} + +bool PluginWindow::isWindowCreated() +{ + return windowCreated; +} + +void PluginWindow::Show() +{ + ShowWindow(hwnd, SW_SHOW); +} + +bool PluginWindow::isActive() +{ + return hwnd && IsWindow(hwnd); +} + +void PluginWindow::Update() +{ + MSG msg; + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + DispatchMessage(&msg); + } +} + +bool PluginWindow::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: + return true; + + case WM_CLOSE: + DestroyWindow(hwnd); + return true; + + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED) + { + /* + // it may be a button or a checkbox. @TODO buttons are used as checkboxes for now. They are triggered by pressing the Play button in the Wwise editor. + if(LOWORD(wParam) == IDC_BUTTON_NEW) + { + // AKPLATFORM::OutputDebugMsg("Button clicked!\n"); + } + else if (LOWORD(wParam) == IDC_CHECKBOX_NEW) + { + LRESULT state = SendDlgItemMessage(hwnd, IDC_CHECKBOX_NEW, BM_GETCHECK, 0, 0); + bool isChecked = (state == BST_CHECKED); + // if (isChecked) + // AKPLATFORM::OutputDebugMsg("Checkbox checked!\n"); + // else AKPLATFORM::OutputDebugMsg("Checkbox unchecked!\n"); + } + */ + int previewID = LOWORD(wParam); + LRESULT state = SendDlgItemMessage(hwnd, previewID, BM_GETCHECK, 0, 0); + float value = (state == BST_CHECKED) ? 1.0f : .0f; + checkBoxValues[previewID]->store(value); + } + return true; + case WM_HSCROLL: + { + HWND slider = reinterpret_cast(lParam); + int ctrID = GetDlgCtrlID(slider); + SliderVal& val = sliderValues[ctrID]; + + int pos = static_cast(SendMessage(slider, TBM_GETPOS, 0, 0)); + + // update slider value + // float actualValue = val.minVal + pos * val.step; + float actualValue = val.minVal + (pos - static_cast(std::round(val.minVal / val.step))) * val.step; + wchar_t valueTxt[16]; + swprintf(valueTxt, 16, L"%.3f", actualValue); + SetWindowText(val.hWnd, valueTxt); + + val.value->store(actualValue); + + return true; + } + case WM_TIMER: + UpdateMonitoringValues(); + return true; + + case WM_QUIT: + { + Close(); + return false; + } + case WM_VSCROLL: + { + // TODO: This case needs much much work. + SCROLLINFO si = { sizeof(si) }; + si.fMask = SIF_ALL; + GetScrollInfo(hwnd, SB_VERT, &si); // SB_VERT for WS_VSCROLL, SB_CTL for scrollbar control + int oldPos = si.nPos; + + // Determine new scroll position + switch (LOWORD(wParam)) + { + case SB_LINEUP: si.nPos -= 10; break; // scroll up 10 pixels + case SB_LINEDOWN: si.nPos += 10; break; // scroll down 10 pixels + case SB_PAGEUP: si.nPos -= si.nPage; break; + case SB_PAGEDOWN: si.nPos += si.nPage; break; + case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; + case SB_THUMBPOSITION: si.nPos = si.nTrackPos; break; + } + + // Clamp to valid range + if (si.nPos < si.nMin) si.nPos = si.nMin; + if (si.nPos > si.nMax - (int)si.nPage) si.nPos = si.nMax - si.nPage; + + // Set updated scroll position + si.fMask = SIF_POS; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + + int delta = si.nPos - oldPos; // how far to scroll + + if (delta != 0) + { + HWND child = GetWindow(hwnd, GW_CHILD); + while (child) + { + RECT rc; + GetWindowRect(child, &rc); + MapWindowPoints(nullptr, hwnd, (POINT*)&rc, 2); + SetWindowPos(child, nullptr, rc.left, rc.top - delta, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + child = GetNextWindow(child, GW_HWNDNEXT); + } + } + + return 0; + } + } + // UpdateMonitoringValues(); + return false; +} + +void PluginWindow::configureWindowScrolling() +{ + // messes up the scrolling functionallity + SCROLLINFO si = { sizeof(si) }; + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; // top of content + si.nMax = curr_height - 1; // bottom of content + si.nPage = cfg.preview.height; // visible client height + si.nPos = 0; // initial scroll position + + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); +} + +LRESULT CALLBACK PluginWindow::StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PluginWindow* pThis = nullptr; + + if (msg == WM_NCCREATE) + { + // store the class pointer ('this') from lpCreateParams within GWLP_USERDATA to retrieve it in the next iteration + CREATESTRUCT* cs = reinterpret_cast(lParam); + pThis = reinterpret_cast(cs->lpCreateParams); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis); + } + else + { + pThis = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + } + + if (pThis && pThis->WindowProc(hwnd, msg, wParam, lParam)) + return 0; + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +bool PluginWindow::createWindow() +{ + // setup before creating window.. + WNDCLASS wc = {}; + wc.lpfnWndProc = StaticWndProc; + wc.hInstance = nullptr; + wc.lpszClassName = windowTitle; + if (!GetClassInfo(nullptr, windowTitle, &wc)) + { + RegisterClass(&wc); + } + + hwnd = CreateWindowEx( + 0, + windowTitle, + windowTitle, + WS_OVERLAPPEDWINDOW | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_VSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, cfg.preview.width,cfg.preview.height, + parentWnd, nullptr, nullptr, this); + + if (createUIcontrols()) + { + // configureWindowScrolling(); + return true; + } + + return false; +} + +bool PluginWindow::createUIcontrols() +{ + if (hwnd) + { + bool success; + for (Parameter& p : parameters) + { + // set the preview.id + p.preview.id = p.index + int(PREVIEW_ID_BASE); + + if (p.type == "button") + // success = CreateButton(p); // @TODO Fix : buttons are replaced with checkboxes. Need to find a way to reset the button after it is pressed to a non-pressed state after it is consumed by the (faust) compute function. + success = CreateCheckbox(p); + else if (p.type == "checkbox") + success = CreateCheckbox(p); + else if (p.type == "slider") + success = CreateSlider(p); + else if (p.type == "bargraph" ) + success = CreateMonitor(p); + else + break; + curr_height+=y_span; + } + + SetTimer(hwnd, 1, 100, nullptr); + + return success; + } + return false; +} + +bool PluginWindow::ProcessMessages() +{ + MSG msg; + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + return false; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return true; +} + +bool PluginWindow::CreateButton(Parameter& p) +{ + HWND hButton = CreateWindow( + L"BUTTON", // Predefined button class + PluginUtils::string2wstring(p.shortname).c_str(), // title + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // stylee + 10, curr_height, 100, 30, // x, y , width, height + hwnd, // parent window + (HMENU)p.preview.id, // IDC alternative + nullptr, // hInstance from GetResourceHandle + nullptr // nevermind + ); + + if(!hButton) + return false; + return true; +} + +bool PluginWindow::CreateCheckbox(Parameter& p) +{ + HWND hCheck = CreateWindow( + L"BUTTON", + PluginUtils::string2wstring(p.shortname).c_str(), + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, + 10, curr_height, p.shortname.length()*12, 30, // x, y, width, height + hwnd, + (HMENU)p.preview.id, + nullptr, + nullptr + ); + if(!hCheck) + return false; + + UINT val = (p.init>0) ? BST_CHECKED : BST_UNCHECKED; // default is unchecked + SendDlgItemMessage(hwnd, p.preview.id, BM_SETCHECK, val , 0); + + checkBoxValues[p.preview.id] = &p.value; + + return true; +} + +bool PluginWindow::CreateSlider(Parameter& p) +{ + int curr_width = p.shortname.length()*12; + // create the text first + HWND hText = CreateWindow( + L"STATIC", + PluginUtils::string2wstring(p.shortname).c_str(), + WS_CHILD | WS_VISIBLE, + 10, curr_height, curr_width, y_span, + hwnd, + nullptr, + nullptr, + nullptr + ); + + if (!hText) + return false; + + int scaledMin = static_cast(std::round(p.pmin / p.step)); + int scaledMax = static_cast(std::round(p.pmax / p.step)); + int scaledInit = static_cast(std::round(p.init / p.step)); + + curr_width += x_margin+10; + // create the slider itself + HWND hSlider = CreateWindowEx( + 0, + TRACKBAR_CLASS, + L"", + WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS, + curr_width, curr_height, 200, y_span, + hwnd, + (HMENU)p.preview.id, + nullptr, + nullptr + ); + + if (!hSlider) + return false; + + SendMessage(hSlider, TBM_SETRANGE, TRUE, MAKELONG(scaledMin, scaledMax)); + SendMessage(hSlider, TBM_SETPOS, TRUE, scaledInit); + + curr_width += x_margin+210; + // label for displaying the value + HWND hwndSliderValue = CreateWindow( + L"STATIC", + std::to_wstring(p.init).c_str(), + WS_CHILD | WS_VISIBLE, + curr_width, curr_height, 60, y_span, + hwnd, + nullptr, + nullptr, + nullptr + ); + + if (!hwndSliderValue) + return false; + + SliderVal val; + val.hWnd = hwndSliderValue; + val.minVal = p.pmin; + val.maxVal = p.pmax; + val.step = p.step; + val.value = &p.value; + + sliderValues[p.preview.id] = val; + + return true; +} + + +bool PluginWindow::CreateMonitor(Parameter& p) +{ + int curr_width = p.shortname.length()*12; + // Label for the monitor + HWND hText = CreateWindow( + L"STATIC", + PluginUtils::string2wstring(p.shortname).c_str(), + WS_CHILD | WS_VISIBLE, + 10, curr_height, curr_width, y_span, // x, y, width, height + hwnd, + nullptr, + nullptr, + nullptr + ); + + if (!hText) + return false; + + curr_width+= x_margin; + // Value display + HWND hwndMonitorValue = CreateWindow( + L"STATIC", + std::to_wstring(p.init).c_str(), + WS_CHILD | WS_VISIBLE | SS_RIGHT, // right-aligned text + curr_width, curr_height, 60, y_span, + hwnd, + nullptr, + nullptr, + nullptr + ); + + if (!hwndMonitorValue) + return false; + + monitorValues.push_back({hwndMonitorValue, &p.value}); + + return true; +} + +void PluginWindow::UpdateMonitoringValues() +{ + for (auto& monitorVar : monitorValues) + { + wchar_t buffer[32]; + swprintf(buffer, 32, L"%.2f", monitorVar.second->load()); + SetWindowText(monitorVar.first, buffer); + } +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.h new file mode 100644 index 0000000000..e0bc66e08f --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/UI/plugin_window.h @@ -0,0 +1,79 @@ +#ifndef PLUGIN_WINDOW_H +#define PLUGIN_WINDOW_H + + +#include "Parameters/parameter.h" +#include "PluginInfo/plugin_config.h" +#define _AFXDLL +#include +#include +#include + +#define DEFAULT_Y_SPAN 25 +#define DEFAULT_X_MARGIN 20 +#define SLIDER_RESOLUTION 1000 // for increasing Slider resolution + +struct SliderVal +{ + HWND hWnd; + float minVal; + float maxVal; + float step; + std::atomic* value; +}; + +class PluginWindow +{ +public: + /* constructor */ + PluginWindow(HWND, PluginConfiguration&, ParameterList&); + + /* destructor */ + ~PluginWindow(); + + /* Returns if a plugin window object is created on initialization or not. */ + bool isWindowCreated(); + + /* Function that shows the plugin window.*/ + void Show(); + + /* Function that verifies that the window is still alive and IsWindow, or destroyed/unset. */ + bool isActive(); + + /* Function that dispatches messages to the window proc function. */ + void Update(); + + /* Implicit destructor.*/ + void Close(); + +private: + + HWND hwnd, parentWnd; + ParameterList& parameters; + PluginConfiguration& cfg; + + bool WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + bool createWindow(); + bool createUIcontrols(); + static bool ProcessMessages(); + bool CreateButton(Parameter&); + bool CreateCheckbox(Parameter&); + bool CreateSlider(Parameter&); + bool CreateMonitor(Parameter& p); + void UpdateMonitoringValues(); + void configureWindowScrolling(); + + std::unordered_map sliderValues; + std::vector*>> monitorValues; + std::unordered_map*> checkBoxValues; + + //ui config + bool windowCreated; + const int y_span, x_margin; + int curr_height; + const wchar_t* windowTitle; +}; + + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.cpp new file mode 100644 index 0000000000..9c6b3c3d99 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.cpp @@ -0,0 +1,40 @@ +#include "abstract.h" + +AbstractPlugin::AbstractPlugin(PluginConfiguration& config, ParameterList& params, InterpreterWrapper& interpreter) + : cfg(config) + , parameters(params) + , faustInterpreter(interpreter) +{ +} + +AbstractPlugin::~AbstractPlugin(){ + reset(); +} + +void AbstractPlugin::setup() +{ + faust_outputs.resize(cfg.num_outputs); +} + +void AbstractPlugin::reset() +{ + faust_outputs.clear(); + +} + +void AbstractPlugin::setParameters() +{ + for (auto& p : parameters){ + + if (p.type!="bargraph") + { + faustInterpreter.setParameter(p.shortname,p.value.load()); + } + else + { + p.value.store(faustInterpreter.getParameter(p.shortname)); + } + + } + +} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.h new file mode 100644 index 0000000000..b0032a5624 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginTemplate/abstract.h @@ -0,0 +1,41 @@ +#ifndef TEMPLATE_ABSTRACT_PLUGIN_H +#define TEMPLATE_ABSTRACT_PLUGIN_H + +#include "PluginInfo/plugin_config.h" +#include "Parameters/parameter.h" +// #include "Interpreter/debugDSP.h" +#include "Interpreter/wrapper.h" + +typedef uint32_t AkUInt32; + +class AbstractPlugin{ +public: + + /* Constructor */ + AbstractPlugin(PluginConfiguration&, ParameterList&, InterpreterWrapper&); + + /* Destructor */ + virtual ~AbstractPlugin(); + + /* Function that resets the plugin to its initial state. */ + virtual void reset(); + + /* Function to allow any type of preprocessing before audio streaming commence. */ + virtual void setup(); + + /* Pure virtual audio callback function. Is implemented differently on the children classes (source, effect). */ + virtual void callback(std::vector&, const AkUInt32)=0; + +protected: + + void setParameters(); + + PluginConfiguration& cfg; + ParameterList& parameters; + InterpreterWrapper& faustInterpreter; + + std::vector faust_outputs; + +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.cpp new file mode 100644 index 0000000000..b6ee7bcf3a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.cpp @@ -0,0 +1,219 @@ +#include "plugin_utils.h" +#include +#include +#include +#include + +// for the createTempDir +#include +#include +#include +#include +#include +#include +#include + + +// for file utils +#include +#include + + +namespace PluginUtils +{ + + std::string ensure_valid_plugin_name(const std::string& name) { + std::string valid = name; + + // replace spaces with underscores + for (auto& c : valid) { + if (c == ' ') { + c = '_'; + } + } + + // ff empty or first char not alphabetic or '_' --> prepend "Dsp_" + if (valid.empty() || !(std::isalpha(valid[0]) || valid[0] == '_')) { + valid = "Dsp_" + valid; + } + + // capitalize first char + if (!valid.empty()) { + valid[0] = static_cast(std::toupper(valid[0])); + } + + return valid; + } + + + bool moveFile(const std::string& sourcePath, const std::string& destPath) + { + try { + std::filesystem::path src(sourcePath); + std::filesystem::path dst(destPath); + + if (!std::filesystem::exists(src)) { + std::cerr << "Source file does not exist: " << src << '\n'; + return false; + } + + std::filesystem::copy_file(src, dst, std::filesystem::copy_options::overwrite_existing); + std::filesystem::remove(src); // Delete original + return true; + } + catch (const std::filesystem::filesystem_error& e) { + std::cerr << "Filesystem error: " << e.what() << '\n'; + return false; + } + } + + // TODO: discard timestamp and use the plugin name for the new directory. + std::string createTempDir(const std::string& exportPath) + { + std::ostringstream timestamp; + auto now = std::chrono::system_clock::now(); + auto now_time_t = std::chrono::system_clock::to_time_t(now); + timestamp << std::put_time(std::localtime(&now_time_t), "%Y%m%d_%H%M%S"); + + std::filesystem::path tempDirectory = std::filesystem::path( exportPath + "/" + timestamp.str()); + + try { + std::filesystem::create_directories(tempDirectory); + // std::filesystem::remove(tempDirectory); //TODO : uncomment later + } catch (const std::filesystem::filesystem_error& e) { + // handle failure to create directory + return false; + } + return tempDirectory.string(); + } + + std::string wstring2string(const std::wstring wstr) + { + std::wstring_convert> converter; + return converter.to_bytes(wstr); + } + + std::wstring string2wstring(const std::string str) + { + std::wstring_convert> converter; + return converter.from_bytes(str); + } + + + std::string parsePluginConfiguration(const std::string& filepath, int numLines) + { + std::ifstream file(filepath); + if (!file.is_open()) { + return {}; + } + + std::deque buffer; + std::string line; + while (std::getline(file, line)) { + buffer.push_back(line); + if (buffer.size() > static_cast(numLines)) + buffer.pop_front(); + } + + buffer.pop_front();// discard last line; + + std::ostringstream out; + for (const auto& l : buffer) + out << l << '\n'; + + return out.str(); + } + + bool load_utf16_file(const std::string& path, std::wstring& buffer) + { + std::ifstream file(path, std::ios::binary); + if (!file) return false; + + // Read raw bytes + std::vector bytes( + (std::istreambuf_iterator(file)), + std::istreambuf_iterator() + ); + + // Must be even-sized (UTF-16) + if (bytes.size() % 2 != 0) + return false; + + buffer.resize(bytes.size() / 2); + memcpy(buffer.data(), bytes.data(), bytes.size()); + + return true; + } + + bool store_utf16_file(const std::string& path, const std::wstring& buffer) + { + std::ofstream file(path, std::ios::binary | std::ios::trunc); + if (!file) return false; + + file.write( + reinterpret_cast(buffer.data()), + buffer.size() * sizeof(wchar_t) + ); + + return true; + } + + #include + #include + bool runElevatedScript(const std::wstring& exe,const std::wstring& args) + { + SHELLEXECUTEINFOW sei = { sizeof(sei) }; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = L"runas"; // elevation + sei.lpFile = exe.c_str(); + sei.lpParameters = args.c_str(); + sei.nShow = SW_SHOWNORMAL; + + if (!ShellExecuteExW(&sei)) + return false; + + // wait to finish + WaitForSingleObject(sei.hProcess, INFINITE); + DWORD exitCode = 0; + GetExitCodeProcess(sei.hProcess, &exitCode); + CloseHandle(sei.hProcess); + + return exitCode == 0; + } + + + void createBatScript(const std::string& scriptPath) + { + if (!std::filesystem::exists(scriptPath)) + { + std::ofstream out(scriptPath); + out << + R"(@echo off +REM Parameters +set "TempDir=%1" +set "PluginName=%2" +set "UseDouble=%3" +set "IsOutOfPlace=%4" + +echo Building plugin in elevated mode... +cd /d "%TempDir%" + +REM Convert boolean flag into faust argument +set "DP_FLAG=" +if "%UseDouble%"=="1" ( + set "DP_FLAG=-double" +) + +REM Out-of-place flag (empty if not enabled) +set "OP_FLAG=" +if "%IsOutOfPlace%"=="1" ( + set "OP_FLAG=--out-of-place" +) + +faust2wwise "%PluginName%.dsp" %DP_FLAG% %OP_FLAG% > output.log 2>&1 +exit /b %ERRORLEVEL% + )"; + out.close(); + } + } +} \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.h new file mode 100644 index 0000000000..bb7040c89a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/plugin_utils.h @@ -0,0 +1,43 @@ +#ifndef PLUGIN_UTILS_H +#define PLUGIN_UTILS_H + +#include + +namespace PluginUtils{ + + /* + Converts the plugin name to a valid format accepted by Wwise. + Adjustments include: + - Prefixing with "Dsp_" if name starts with a number or is invalid + - Replacing spaces with underscores + - Capitalizing the first character + */ + std::string ensure_valid_plugin_name(const std::string& name); + + /* Function to move a file from source to dest. */ + bool moveFile(const std::string&, const std::string&); + + /* Function that creates a new unique directory named with a timestamp. + * This dir will be created within the directory of the string that is passed as an argument. */ + std::string createTempDir(const std::string&); + + /* Convert a wide string to string and vice versa. */ + std::string wstring2string(const std::wstring); + std::wstring string2wstring(const std::string); + + /* Function that iterates over the last lines of the output.log file, and returns the plugin configuration printed on those lines. */ + std::string parsePluginConfiguration(const std::string&, const int numLines = 7); + + /* Writes a buffer to a UTF-16 encoded text file. */ + bool store_utf16_file(const std::string& path, const std::wstring& buffer); + /* Loads a buffer from a UTF-16 encoded text file. */ + bool load_utf16_file(const std::string& path, std::wstring& buffer); + + /* Runs a script with administrative rights. Here it is used to build plugins using faust2wwise. */ + bool runElevatedScript(const std::wstring& exe,const std::wstring& args); + /* Creates(/Generates) a script and stores it on disk on the fly. */ + void createBatScript(const std::string& scriptPath); + +} + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.cpp new file mode 100644 index 0000000000..dc9a709097 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.cpp @@ -0,0 +1,40 @@ +#include "syscall.h" +#include +#include +#include +#include +#include +#include + +namespace SysCall{ + + inline std::string normalizePath(const std::string& path) { + std::string normalized = path; + std::replace(normalized.begin(), normalized.end(), '\\', '/'); + return normalized; + } + + std::string getEnvVar(const std::string& varName) { + const char* value = std::getenv(varName.c_str()); + return value ? normalizePath(std::string(value)) : ""; // return empty string if not found + } + + std::string execCommand(const std::string& cmd) { + std::array buffer; + std::string result; + + // Open pipe using _popen + std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose); + if (!pipe) { + throw std::runtime_error("_popen() failed!"); + } + + // Read output + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + return normalizePath(result.substr(0, result.size()-1)); // erase \n at the end and normalize path. + } + +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.h new file mode 100644 index 0000000000..4fbf158282 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/PluginUtils/syscall.h @@ -0,0 +1,16 @@ +#ifndef FPLUGIN_SYSCALL_H +#define FPLUGIN_SYSCALL_H + +#include + +namespace SysCall{ + + /* Function that is used to get the Wwise env path. */ + std::string getEnvVar(const std::string& varName); + + /* Function used to call system commands (i.e. faust --dspdir). */ + std::string execCommand(const std::string& cmd); + +} + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/Manager.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/Manager.cpp new file mode 100644 index 0000000000..4d3179d490 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/Manager.cpp @@ -0,0 +1,230 @@ +#include "Manager.h" +#include "entry_code.h" +#include "PluginUtils/plugin_utils.h" +#include +#include +#include +#include +#include + +#define UNTITLED_FILENAME "Untitled" +#define PROJECT_FILES_SUBDIR "ProjectFiles" +#define DEFAULT_CODE_FILENAME "default_entry_code" + +ProjectFilesManager::ProjectFilesManager(std::string& exportPath) + : projectFilesDir(exportPath+'/'+ std::string(PROJECT_FILES_SUBDIR)) + , untitled_filename(std::string(UNTITLED_FILENAME)) +{ + scanProjectFileDir(); +} + +std::vector ProjectFilesManager::getProjectFiles() const { + std::vector filenames; // without extension + for (const std::string& pf : project_files) + { + filenames.push_back(pf); + } + return filenames; +} + +bool ProjectFilesManager::load(const std::string& filename, std::wstring& dspCode) +{ + + if (project_files.find(filename) == project_files.end()) + { + // return default + std::string code = std::string(default_entry_code); + dspCode = PluginUtils::string2wstring(code); + return false; + } + + std::string current_file_path = getFilePath(filename); + + bool fileLoaded = PluginUtils::load_utf16_file(current_file_path, dspCode); + + return fileLoaded; +} + + +bool ProjectFilesManager::create(std::string& filename) +{ + filename = untitled_filename + std::to_string(getNextUntitledNumber()); + + std::string filepath = getFilePath(filename); + if (std::filesystem::exists(filepath)) + { + std::cerr << "File already exists: " << filepath << "\n"; + return false; + } + + if (!writeFile(filename, PluginUtils::string2wstring(std::string(default_entry_code)))) + return false; + + project_files.insert(filename); + return true; +} + +bool ProjectFilesManager::writeFile(const std::string& filename, const std::wstring& contents) const +{ + const std::string filepath = getFilePath(filename); + return PluginUtils::store_utf16_file(filepath,contents); +} + +bool ProjectFilesManager::rename(const std::string& oldName, const std::string& newName) +{ + // remove untitled number from registry + if (!removeUntitledNumber(oldName)){ + std::cout << "Entry "< +#include +#include + +class ProjectFilesManager +{ +public: + /* Constructor */ + ProjectFilesManager(std::string&); + + /* Returns a list of DSP filenames (without the .dsp extension) stored on the disk at a specific location. */ + std::vector getProjectFiles() const; + + /* Function used to load the contents of a dsp file. */ + bool load(const std::string&, std::wstring&); + + /* Function used to create a new dsp file.*/ + bool create(std::string&); + + /* Function used to store a dsp file on disk.*/ + bool writeFile(const std::string&, const std::wstring& contents) const; + + /* Function used to rename a dsp file.*/ + bool rename(const std::string&, const std::string&); + + /* Function used to remove a dsp file.*/ + bool remove(const std::string&); + + /* Returns true if the argument does not exist on the registry of the existing filenames.*/ + bool pfNameUnique(const std::string&); + +private: + + std::string projectFilesDir; + std::set project_files; + std::set usedUntitledNumbers; + std::string untitled_filename; + + void scanProjectFileDir(); + void updateUntitledSet(const std::string&); + size_t getNextUntitledNumber(); + bool removeUntitledNumber(const std::string&); + std::string getFilePath(const std::string&) const; +}; + +#endif diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/entry_code.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/entry_code.h new file mode 100644 index 0000000000..bc4f8b423d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/ProjectFiles/entry_code.h @@ -0,0 +1,10 @@ +// @TODO : Improve the way code in the editor is stored/used +#define LASTCODE_FNAME "last_code.dsp" + +const char* default_entry_code = R"FAUST( +import("stdfaust.lib"); + +declare name "myPlugin"; // declare name of your plugin + +// you faust dsp code here.. +)FAUST"; diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.cpp new file mode 100644 index 0000000000..4a9f1ef0fb --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.cpp @@ -0,0 +1,178 @@ +#include "plugin_loader.h" +#include +#include + +#define BUILD_DIR "_build" + +PluginLoader::PluginLoader() + : pluginState(PluginState::ZERO_STATE) + , effectPlugin(cfg, parameters, faustInterpreter) + , sourcePlugin(cfg, parameters, faustInterpreter) +{ + cfg.path.wwiseRoot = SysCall::getEnvVar("WWISEROOT"); + cfg.path.exportPath = cfg.path.wwiseRoot + '/' + std::string(STORAGE_DIRNAME); + + if (!std::filesystem::exists(cfg.path.exportPath)) { + std::filesystem::create_directory(cfg.path.exportPath); + } + + cfg.path.faust_includedir = SysCall::execCommand("faust --includedir"); + cfg.path.faust_dspdir = SysCall::execCommand("faust --dspdir"); + + cfg.path.archfile = cfg.path.faust_dspdir + "/wwise.cpp"; + +} + +bool PluginLoader::createPlugin(std::string &dspCode, int audioInputID, std::string& errorMsg) +{ + + // reset everything before proceeding + resetPlugin(); + + pluginState.store(PluginState::PENDING_CREATION); + + bool dspCompiled = faustInterpreter.compileDSP(dspCode, cfg, errorMsg); + if (!dspCompiled) + { + pluginState.store(PluginState::ERR_COMPILE_DSP); + return false; + } + pluginState.store(PluginState::DSP_COMPILED); + + bool dspuiCreated = faustInterpreter.createDSPandUI(); + if (!dspuiCreated) + { + pluginState.store(PluginState::ERR_DSPUI_CREATION); + return false; + } + pluginState.store(PluginState::DSPUI_CREATED); + + bool pluginConfigured = faustInterpreter.configurePlugin(cfg, parameters); + if (!pluginConfigured) + { + pluginState.store(PluginState::ERR_CONFIGURE_PLUGIN); + return false; + } + pluginState.store(PluginState::PLUGIN_CONFIGURED); + + // assign plugin pointer to preallocated plugin depending on its type. + if (cfg.plugin_type == "source") + { + plugin = &sourcePlugin; + } + else if (cfg.plugin_type == "effect") + { + plugin = &effectPlugin; + effectPlugin.setAudioInput(audioInputID); + } + + plugin->setup(); + pluginState.store(PluginState::PLUGIN_SET); + + //HINT: setupAudio is pending - will be called when the play button is pressed ... + + return true; +} + +int PluginLoader::setupAudio(int SR) +{ + if (pluginState.load() == PluginState::PLUGIN_SET) + { + faustInterpreter.setupDSP(SR); + cfg.sampleRate = SR; + + if (cfg.plugin_type == "effect") + { + effectPlugin.setSampleRate(SR); + } + + pluginState.store(PluginState::READY); + + return cfg.num_outputs; // return channels requested + + } + return 0; +} + +void PluginLoader::unloadPlugin() +{ + pluginState.store(PluginState::ZERO_STATE); +} + +void PluginLoader::resetPlugin() +{ + pluginState.store(PluginState::ZERO_STATE); + + // reset plugin + if (plugin) + plugin->reset(); + + // unload plugin + plugin = nullptr; + + // reset internal + cfg.reset(); + faustInterpreter.reset(); + + // reset params + parameters.clear(); + parameters.shrink_to_fit(); +} + +void PluginLoader::callback(std::vector& outdata, const AkUInt32 size) +{ + plugin->callback(outdata, size); +} + +#include +#include +#include +bool PluginLoader::buildPlugin( + const std::string& pluginName, + const std::string& dspCode, + bool doublePrecision, + bool isOutOfPlace, + std::string& outputText) { + + std::string tempDir = PluginUtils::createTempDir(cfg.path.exportPath + '/' + std::string(BUILD_DIR) + '/' + pluginName); + + // write dspCode into the example.dsp file. Name of plugin will be set automatically via declare. + std::filesystem::path dspPath = std::filesystem::path(tempDir + '/' + pluginName +".dsp"); + std::ofstream outFile(dspPath); + if (!outFile.is_open()) { + return false; + } + outFile << dspCode; + outFile.close(); + + // use that script to enable user to provide admin rights when running build (via faust2wwise) + // create a powerShell if it doesnt exist + std::string scriptPath = cfg.path.exportPath + "/build_faust_plugin.bat"; + PluginUtils::createBatScript(scriptPath); // runs only the first time. + + std::wstringstream args; + args << L"/c \"\"" + << PluginUtils::string2wstring(scriptPath) << L"\"" + << L" \"" << PluginUtils::string2wstring(tempDir) << L"\"" + << L" \"" << PluginUtils::string2wstring(pluginName) << L"\"" + << L" " << (doublePrecision ? 1 : 0) + << L" " << ((isOutOfPlace) ? 1 : 0) + << L"\""; + + bool result = PluginUtils::runElevatedScript(L"cmd.exe", args.str()); + + std::string logPath = tempDir + "/output.log"; + if (result) + { + int numLines = 7; // last 7 lines contain the plugin configuration + outputText = PluginUtils::parsePluginConfiguration(logPath, numLines); + } + else outputText = logPath; // else return the path to the log file. + + return result; +} + +bool PluginLoader::exportCPP(const std::string &filename, const std::string& dspCode, const std::string& filepath, bool doublePrecision, std::string& errorMessage) +{ + return faustInterpreter.exportCPP(cfg.path.faust_dspdir, filename, dspCode, filepath, doublePrecision, errorMessage); +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.h new file mode 100644 index 0000000000..efde9141e9 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/FaustRuntime/plugin_loader.h @@ -0,0 +1,76 @@ +#ifndef FAUST_PLUGIN_LOADER_H +#define FAUST_PLUGIN_LOADER_H + +#include "PluginUtils/syscall.h" +// #include "Interpreter/debugDSP.h" +#include "Interpreter/wrapper.h" +#include "PluginTemplate/SourcePlugin.h" +#include "PluginTemplate/EffectPlugin.h" +#include "PluginInfo/plugin_state.h" + +/*! + * @brief Singleton class. +*/ +class PluginLoader{ + +public: + + /*! @brief Get instance of the PluginLoader class. Singleton pattern. + * @return PluginLoader& - a reference to the PluginLoader object. + */ + static PluginLoader& getInstance(){ + static PluginLoader faust_plugin; + return faust_plugin; + } + ~PluginLoader() = default; // class destructor. + PluginLoader(const PluginLoader&) = delete; // delete copy constructor + PluginLoader& operator=(const PluginLoader&) = delete; // delete copy assignment operator + PluginLoader(PluginLoader&&) = delete; // delete move constructor + PluginLoader& operator=(PluginLoader&&) = delete; // delete move assignement operator + + /* Returns the configuration */ + PluginConfiguration& getConfiguration() { return cfg; } + /* Returns a list of parameters */ + ParameterList& getParameters() { return parameters; } + /* Returns the plugin state. Plugin state is an atomic variable. */ + PluginState getPluginState() { return pluginState.load(); } + + /* Function to create a new plugin. Called on previewing dsp code. */ + bool createPlugin(std::string&, int, std::string&); + + /* Shares the Sample Rate of the host environment*/ + int setupAudio(int); + /* Function used to set the atomic variable to an exiting value.*/ + void unloadPlugin(); + /* Function used to reset all the internal structures to an null state .*/ + void resetPlugin(); + /* Audio callback function */ + void callback(std::vector&, const AkUInt32); + + /* Function used to build plugin, calling faust2wwise behind the scenes. */ + bool buildPlugin(const std::string&, const std::string&, bool, bool, std::string&); + /* returns the path created ('faust_' dir) with the Wwise root directory. */ + std::string& getExportPath() { return cfg.path.exportPath; } + + /* Compiles the dsp code and stores the cpp code on disk. */ + bool exportCPP(const std::string &filename, const std::string& dspCode, const std::string& filepath, bool doublePrecision, std::string& errorMessage); + +private: + /*! @brief Class constructor. + */ + PluginLoader(); + + InterpreterWrapper faustInterpreter; + + std::atomic pluginState; + PluginConfiguration cfg; + ParameterList parameters; + + AbstractPlugin *plugin; + // preallocate + WwiseEffectPlugin effectPlugin; + WwiseSourcePlugin sourcePlugin; + +}; + +#endif \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/Faust_Interpreter_Wwise_PluginConfig.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/Faust_Interpreter_Wwise_PluginConfig.h new file mode 100644 index 0000000000..62e35bf913 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/Faust_Interpreter_Wwise_PluginConfig.h @@ -0,0 +1,40 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef Faust_Interpreter_Wwise_PluginConfig_H +#define Faust_Interpreter_Wwise_PluginConfig_H + +// NB: In order to properly change the CompanyID / PluginID, you must change them: +// - In this file; +// - In the xml file located in the WwisePlugin directory; +// - In the xml file located in the FactoryAssets directory. +namespace Faust_Interpreter_Wwise_PluginConfig +{ + static const unsigned short CompanyID = 64; + static const unsigned short PluginID = 16291; +} + +#endif // Faust_Interpreter_Wwise_PluginConfig_H diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/PremakePlugin.lua b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/PremakePlugin.lua new file mode 100644 index 0000000000..155a1ea48d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/PremakePlugin.lua @@ -0,0 +1,168 @@ +--[[---------------------------------------------------------------------------- +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +------------------------------------------------------------------------------]] + +if not _AK_PREMAKE then + error('You must use the custom Premake5 scripts by adding the following parameter: --scripts="Scripts\\Premake"', 1) +end + +local Plugin = {} +Plugin.name = "Faust_Interpreter_Wwise_Plugin" +Plugin.factoryheader = "../SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceFactory.h" +Plugin.appleteamid = "" +Plugin.signtoolargs = {} +Plugin.sdk = {} +Plugin.sdk.static = {} +Plugin.sdk.shared = {} +Plugin.authoring = {} + +-- SDK STATIC PLUGIN SECTION +Plugin.sdk.static.includedirs = -- https://github.com/premake/premake-core/wiki/ +{ + "../FaustRuntime", +} + +Plugin.sdk.static.files = -- https://github.com/premake/premake-core/wiki/files +{ + "**.cpp", + "**.h", + "**.hpp", + "**.c", + "../FaustRuntime/**.cpp", + "../FaustRuntime/**.h", +} +Plugin.sdk.static.excludes = -- https://github.com/premake/premake-core/wiki/removefiles +{ + "Faust_Interpreter_Wwise_PluginSourceShared.cpp" +} +Plugin.sdk.static.links = -- https://github.com/premake/premake-core/wiki/links +{ + "libfaust", +} + +Plugin.sdk.static.libsuffix = "Source" +Plugin.sdk.static.libdirs = -- https://github.com/premake/premake-core/wiki/libdirs +{ +} +Plugin.sdk.static.defines = -- https://github.com/premake/premake-core/wiki/defines +{ +} + +-- SDK SHARED PLUGIN SECTION +Plugin.sdk.shared.includedirs = +{ + "../FaustRuntime", +} +Plugin.sdk.shared.files = +{ + "Faust_Interpreter_Wwise_PluginSourceShared.cpp", + "Faust_Interpreter_Wwise_PluginSourceFactory.h", + "../FaustRuntime/**.cpp", + "../FaustRuntime/**.h", +} +Plugin.sdk.shared.excludes = +{ +} +Plugin.sdk.shared.links = +{ +} +Plugin.sdk.shared.libdirs = +{ +} +Plugin.sdk.shared.defines = +{ +} + +-- AUTHORING PLUGIN SECTION +Plugin.authoring.includedirs = +{ + "../FaustRuntime", +} +Plugin.authoring.files = +{ + "**.cpp", + "**.h", + "**.hpp", + "**.c", + "Faust_Interpreter_Wwise_Plugin.def", + "Faust_Interpreter_Wwise_Plugin.xml", + "**.rc", +} +Plugin.authoring.excludes = +{ +} +Plugin.authoring.links = +{ +} +Plugin.authoring.libdirs = +{ +} +Plugin.authoring.defines = +{ +} + +-------------------------------------------------------------------------------- FAUST2WWISE ADDITIONS + +local function faustQuery(arg) + local cmd = "faust " .. arg + local pipe = io.popen(cmd) + if not pipe then + return nil + end + + local result = pipe:read("*l") + pipe:close() + + if result == "" then + return nil + end + + return result +end + +local faustLibDir = faustQuery("-libdir") +local faustIncludeDir = faustQuery("-includedir") + +if not faustLibDir or not faustIncludeDir then + error("Faust not found. Ensure Faust is installed and available on PATH.", 1) +else + -- .. add include dir into the includedirs sections + table.insert(Plugin.sdk.static.includedirs, faustIncludeDir) + table.insert(Plugin.sdk.shared.includedirs, faustIncludeDir) + table.insert(Plugin.authoring.includedirs, faustIncludeDir) + + -- .. add include dir into the includedirs sections + table.insert(Plugin.sdk.static.libdirs, faustLibDir) + + -- .. add libfaustwithllvm into the Plugin.sdk.static.links sections + if os.isfile(faustLibDir .. "/libfaustwithllvm.lib") then -- if Faust is configured with LLVM by checking if lib file exists in libdir + print("Faust LLVM backend detected: enabling libfaustwithllvm") + table.insert(Plugin.sdk.static.links, "libfaustwithllvm") + else + print("Faust LLVM backend NOT detected: building without LLVM") + end +end + +return Plugin \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/README.md b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/README.md new file mode 100644 index 0000000000..87a265bba2 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/README.md @@ -0,0 +1,102 @@ +# Faust Interpreter Wwise Plugin + +This project integrates the Faust IDE as a plugin directly into Wwise Authoring SDK, providing an environment to edit, preview, and build Faust DSP code inside Wwise. **Currently, it is supported only for Windows**. + +

+ +Integrated Faust interpreter as a Wwise Plugin + +

+ +## Supported Features + +- Code editor +- Integrated Faust interpreter +- Build option. This utilizes `faust2wwise` for building dsp code as a Wwise plugin. +- Preview option. +- Source plugin integration support +- Effect plugin integration support with multiple Audio Input generators for testing effects. +- Parameter integration including buttons, checkboxes, sliders, bargraphs. +- Export options +- Project Filelist (internal / UI / filesystem) that allows to: + - create new project files, + - rename project files, + - delete project files, +- Double Precision support for building and exporting. +- `in place` and `out-of-place` option for building effect plugins. +- Admin rights handling (prompting via Windows elevation) +- Integrated local Faust documentation + +## Future-list + +- [ ] Improve Code Editor: + - [ ] additional shortcuts + - [ ] resizable window +- [ ] Integrated output console +- [ ] Fix scrolling issues in the plugin window (particularly with many parameters) +- [x] Fix audio duration (numLoops) + - numLoops is disabled. +- [ ] add support for macOS +- [x] integrate within `faust2wwise` +- [ ] replace faust interpreter with faust compiler +- [x] automate Faust include and lib directories detection at premake time + +## Build Instructions + +With **Faust** and **Wwise** installed, and having **WWISEROOT** exposed system-wide, the Faust Interpreter Wwise Plugin can be installed by running: + +``` +faust2wwise interpreter-install +``` + +Or with explicit build arguments: + +``` +faust2wwise interpreter-install --arch x64 --tooset vc170 +``` + +> Ensure the correct `Windows SDK` is installed for your Wwise version. For instance, for Wwise 2024.1.12, see [Windows Build requirements](https://www.audiokinetic.com/en/public-library/2024.1.12_9034/?source=SDK&id=windows_releasenotes_2024_1_12.html). For other versions see [Windows Release Notes](https://www.audiokinetic.com/en/public-library/2024.1.12_9034/?source=SDK&id=windows_releasenotes.html). For more details, you may refere to the [Faust_Interpreter_Test_Plugin build instructions](https://github.com/grame-cncm/faust2wwise/tree/main/Faust_Interpreter_Test_Plugin#build-instructions) + +## Usage + +Use the code editor to write Faust DSP code. +Pressing Preview checks the compilation status and, if successful, opens a preview instance of the plugin. +The `Build` option compiles the DSP code into a Wwise plugin using `faust2wwise`. After a successful build, **Wwise must be restarted** for the new plugin to appear in the Wwise plugin menu. + +For effect plugins, multiple audio input choices are available to provide a test signal for evaluating the effect. + +The `Project Files` menu supports creating, renaming, and deleting DSP project files. + +The `Export` option stores the compiled DSP code on disk. +Selecting `Save DSP Code` also saves the source `.dsp` file to disk. + +The `Double Precision` option enables double-precision internal DSP computation in the exported file. +When building, enabling double precision compiles the plugin using the same precision mode. + +Enabling `Out of place` makes the processing use separate input and output buffers in the Execute and compute functions. + +Finally, `Docs` redirects to the online Faust documentation. + +## Troubleshooting + +
+ +
+Scrolling along the plugin window in Preview has visual artifacts. +
+ +This is a known issue. Compiling a DSP implementation that contains a considerable number of parameters (more than can fit on a user's screen) enables scrolling, but it is currently broken and needs to be fixed. + +
+ +
+ +
+Can' t loop audio in Wwise. +
+ +This feature is currently deactivated to eliminate audio artifacts. Check the [Future List](#future-list). + +
+ +
\ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.cpp new file mode 100644 index 0000000000..966f19eefe --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.cpp @@ -0,0 +1,245 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#include "Faust_Interpreter_Wwise_PluginSource.h" +#include "../Faust_Interpreter_Wwise_PluginConfig.h" +#include +#include + +AK::IAkPlugin* CreateFaust_Interpreter_Wwise_PluginSource(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, Faust_Interpreter_Wwise_PluginSource()); +} + +AK::IAkPluginParam* CreateFaust_Interpreter_Wwise_PluginSourceParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, Faust_Interpreter_Wwise_PluginSourceParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(Faust_Interpreter_Wwise_PluginSource, AkPluginTypeSource, Faust_Interpreter_Wwise_PluginConfig::CompanyID, Faust_Interpreter_Wwise_PluginConfig::PluginID) + +Faust_Interpreter_Wwise_PluginSource::Faust_Interpreter_Wwise_PluginSource() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ + +} + +Faust_Interpreter_Wwise_PluginSource::~Faust_Interpreter_Wwise_PluginSource() +{ +} + +AkUInt32 Faust_Interpreter_Wwise_PluginSource::GetSpeakerConfigChannelMask(int preAllocatedOutputs){ + + // provide default configurations based on given faust dsp outputs + + AkUInt32 in_uChannelMask; + switch (preAllocatedOutputs) + { + case 1: + in_uChannelMask = AK_SPEAKER_SETUP_MONO; + break; + case 2: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + case 3: + in_uChannelMask = AK_SPEAKER_SETUP_3STEREO; + break; + case 4: + in_uChannelMask = AK_SPEAKER_SETUP_4; + break; + case 5: + in_uChannelMask = AK_SPEAKER_SETUP_5; + break; + case 6: + in_uChannelMask = AK_SPEAKER_SETUP_6; + break; + case 7: + in_uChannelMask = AK_SPEAKER_SETUP_7; + break; + case 8: + in_uChannelMask = AK_SPEAKER_SETUP_7POINT1; + break; + case 9: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9; + break; + case 10: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9POINT1; + break; + case 11: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_10POINT1; + break; + case 12: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_11POINT1; + break; + case 13: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13_751; + break; + case 14: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + break; + default: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + } + if (preAllocatedOutputs > 14) + { + AKPLATFORM::OutputDebugMsg(" [WARNING] dsp_outputs > 14. This is an unsupported speaker configuration. Falling back to 14 channels (AK_SPEAKER_SETUP_AURO_13POINT1_751).\n"); + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + } + + return in_uChannelMask; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSource::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (Faust_Interpreter_Wwise_PluginSourceParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + AKPLATFORM::OutputDebugMsg("Init is called!\n"); + + PluginState state = pluginLoader.getPluginState(); + + if (state != PluginState::READY) + { + + m_durationHandler.Setup(0.0f, in_pContext->GetNumLoops(), in_rFormat.uSampleRate); + + int channelsRequested = pluginLoader.setupAudio( + static_cast(in_rFormat.uSampleRate) + ); + // Set the speaker configuration + in_rFormat.channelConfig.SetStandard( GetSpeakerConfigChannelMask(channelsRequested) ); + speakersAvail = in_rFormat.channelConfig.uNumChannels; + + WwiseOutputs.resize(speakersAvail, nullptr); + + isInitializedOnce = true; + return AK_Success; + } + isInitializedOnce = false; + return AK_AlreadyInitialized; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSource::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AKPLATFORM::OutputDebugMsg("Term is called!\n"); + + if (isInitializedOnce) + { + // that is an reset signal + pluginLoader.resetPlugin(); + } + else + { + // that is a subsequent Play trigger, so reset the variable to true. + isInitializedOnce = true; + } + + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSource::Reset() +{ + AKPLATFORM::OutputDebugMsg("Reset is called!\n"); + return AK_Success; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSource::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeSource; + out_rPluginInfo.bIsInPlace = true; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +/* +void Faust_Interpreter_Wwise_PluginSource::initializeAllChannelsWithSilence(const AkUInt32 framesToProcess) +{ + // Runs only once filling the rest of the faust output channels with silence, ... + // ... and only in case the channels requested by the faust dsp program is greater + // than the available channels wwise can support. + + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + + // Fill silent channels + if (!WwiseOutputs[speakersAvail-1]) // if the last buffer is nullptr + { + for (AkUInt32 ch = 0; ch < speakersAvail; ++ch) { + WwiseOutputs[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled the silence buffer!\n"); + } + } +} + */ + +void Faust_Interpreter_Wwise_PluginSource::Execute(AkAudioBuffer* out_pBuffer) +{ + + if ( pluginLoader.getPluginState() == PluginState::READY) + { + m_durationHandler.SetDuration(m_pParams->RTPC.fDuration); + m_durationHandler.ProduceBuffer(out_pBuffer); + + const AkUInt32 uNumChannels = out_pBuffer->NumChannels(); + const AkUInt32 framesToProcess = out_pBuffer->uValidFrames; + + for (AkUInt32 i = 0; i < speakersAvail; ++i) + { + WwiseOutputs[i] = (AkReal32* AK_RESTRICT) out_pBuffer->GetChannel(i); + } + AKPLATFORM::OutputDebugMsg("Execute function is running!\n"); + pluginLoader.callback(WwiseOutputs, framesToProcess); + + } + else{ + m_durationHandler.SetDuration(0.0f); + m_durationHandler.SetLooping(1.0f); // @TODO : Enable user to loop endlesly. Currently this is disabled. + m_durationHandler.ProduceBuffer(out_pBuffer); + // for (AkUInt32 i = 0; i < speakersAvail; ++i) + // { + // AkReal32* AK_RESTRICT pBuf = (AkReal32* AK_RESTRICT)out_pBuffer->GetChannel(i); + // // pBuf->ZeroPadToMaxFrames(); + // AkUInt16 uFramesProduced = 0; + // while (uFramesProduced < out_pBuffer->uValidFrames) + // { + // // Generate output here + // *pBuf++ = 0.0f; + // ++uFramesProduced; + // } + // } + } +} + +AkReal32 Faust_Interpreter_Wwise_PluginSource::GetDuration() const +{ + return m_durationHandler.GetDuration() * 1000.0f; +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.h new file mode 100644 index 0000000000..2518adbab2 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSource.h @@ -0,0 +1,80 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef Faust_Interpreter_Wwise_PluginSource_H +#define Faust_Interpreter_Wwise_PluginSource_H + +#include "Faust_Interpreter_Wwise_PluginSourceParams.h" +#include +#include "plugin_loader.h" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__source.html +/// for the documentation about source plug-ins +class Faust_Interpreter_Wwise_PluginSource + : public AK::IAkSourcePlugin +{ +public: + Faust_Interpreter_Wwise_PluginSource(); + ~Faust_Interpreter_Wwise_PluginSource(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Source plug-in DSP execution. + void Execute(AkAudioBuffer* io_pBuffer) override; + + /// This method is called to determine the approximate duration (in ms) of the source. + AkReal32 GetDuration() const override; + +private: + Faust_Interpreter_Wwise_PluginSourceParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkSourcePluginContext* m_pContext; + AkFXDurationHandler m_durationHandler; + + PluginLoader& pluginLoader = PluginLoader::getInstance(); + AkUInt32 Faust_Interpreter_Wwise_PluginSource::GetSpeakerConfigChannelMask(int predefinedOutputs); + int speakersAvail; + std::vector WwiseOutputs; + // std::vector silenceBuffer; + // void initializeAllChannelsWithSilence(const AkUInt32); + + bool isInitializedOnce; +}; + +#endif // Faust_Interpreter_Wwise_PluginSource_H diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceFactory.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceFactory.h new file mode 100644 index 0000000000..a3aee4eea0 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceFactory.h @@ -0,0 +1,32 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef Faust_Interpreter_Wwise_PluginSourceFactory_H +#define Faust_Interpreter_Wwise_PluginSourceFactory_H + +AK_STATIC_LINK_PLUGIN(Faust_Interpreter_Wwise_PluginSource) + +#endif // Faust_Interpreter_Wwise_PluginSourceFactory_H diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.cpp new file mode 100644 index 0000000000..cf00917de5 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.cpp @@ -0,0 +1,100 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#include "Faust_Interpreter_Wwise_PluginSourceParams.h" + +#include + +Faust_Interpreter_Wwise_PluginSourceParams::Faust_Interpreter_Wwise_PluginSourceParams() +{ +} + +Faust_Interpreter_Wwise_PluginSourceParams::~Faust_Interpreter_Wwise_PluginSourceParams() +{ +} + +Faust_Interpreter_Wwise_PluginSourceParams::Faust_Interpreter_Wwise_PluginSourceParams(const Faust_Interpreter_Wwise_PluginSourceParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* Faust_Interpreter_Wwise_PluginSourceParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, Faust_Interpreter_Wwise_PluginSourceParams(*this)); +} + +AKRESULT Faust_Interpreter_Wwise_PluginSourceParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fDuration = 10.0f; + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT Faust_Interpreter_Wwise_PluginSourceParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSourceParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fDuration = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT Faust_Interpreter_Wwise_PluginSourceParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_DURATION_ID: + RTPC.fDuration = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_DURATION_ID); + break; + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.h new file mode 100644 index 0000000000..933c8802bb --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceParams.h @@ -0,0 +1,77 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef Faust_Interpreter_Wwise_PluginSourceParams_H +#define Faust_Interpreter_Wwise_PluginSourceParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_DURATION_ID = 0; +static const AkUInt32 NUM_PARAMS = 1; + +struct Faust_Interpreter_Wwise_PluginRTPCParams +{ + AkReal32 fDuration; +}; + +struct Faust_Interpreter_Wwise_PluginNonRTPCParams +{ +}; + +struct Faust_Interpreter_Wwise_PluginSourceParams + : public AK::IAkPluginParam +{ + Faust_Interpreter_Wwise_PluginSourceParams(); + Faust_Interpreter_Wwise_PluginSourceParams(const Faust_Interpreter_Wwise_PluginSourceParams& in_rParams); + + ~Faust_Interpreter_Wwise_PluginSourceParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + Faust_Interpreter_Wwise_PluginRTPCParams RTPC; + Faust_Interpreter_Wwise_PluginNonRTPCParams NonRTPC; +}; + +#endif // Faust_Interpreter_Wwise_PluginSourceParams_H diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceShared.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceShared.cpp new file mode 100644 index 0000000000..34919d13c4 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceShared.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#include +#include "Faust_Interpreter_Wwise_PluginSourceFactory.h" + +#include + +DEFINEDUMMYASSERTHOOK; +DEFINE_PLUGIN_REGISTER_HOOK; diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust.rc b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust.rc new file mode 100644 index 0000000000..5b0ef7fc9b --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust.rc @@ -0,0 +1,30 @@ +#include "resource.h" +#include +#include + +IDD_FAUST_PLUGIN DIALOGEX 0, 0, 400, 250 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Enter FAUST Code:", -1, 10,10,100,10 + EDITTEXT IDC_CODE_EDITOR, 10,25, 380,150, + ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_BORDER | WS_TABSTOP + PUSHBUTTON "Preview", IDC_BUTTON_PREVIEW, 10, 185, 80, 20 + PUSHBUTTON "Build", IDC_BUTTON_BUILD, 100, 185, 80, 20 + LTEXT "Audio Input:", -1, 210, 13, 70, 10 + COMBOBOX IDC_AUDIO_INPUT_COMBO, 280, 10, 110, 100, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Project Files:", -1, 395, 13, 70, 10 + PUSHBUTTON "+", IDC_NEW_PROJECT_FILE, 445, 10, 20, 14 + PUSHBUTTON "~", IDC_RENAME_PROJECT_FILE, 465, 10, 20, 14 + PUSHBUTTON "-", IDC_DELETE_PROJECT_FILE, 485, 10, 20, 14 + COMBOBOX IDC_PROJECT_FILES_COMBO, 395, 30, 110, 100, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Export", IDC_BUTTON_EXPORT, 190, 185, 80, 20 + CONTROL "Save DSP Code", IDC_CHECK_SAVE_DSP, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 395, 165, 70, 12 + PUSHBUTTON "Docs", IDC_BUTTON_DOCS, 280, 185, 80, 20 + CONTROL "Double Precision", IDC_CHECK_DOUBLE_PRECISION, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 395, 150, 90, 12 + CONTROL "Out-of-place", IDC_CHECK_OUT_OF_PLACE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 395, 135, 90, 12 + +END + diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.def b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.def new file mode 100644 index 0000000000..9c3bf2c14d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.def @@ -0,0 +1,3 @@ +LIBRARY "Faust_Interpreter_Wwise_Plugin" + +EXPORTS diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.xml b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.xml new file mode 100644 index 0000000000..499d457efd --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_Plugin.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + 10.0 + 0 + + + + 0.001 + 1000 + + + + + + + diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.cpp new file mode 100644 index 0000000000..f35b054bff --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#include "Faust_Interpreter_Wwise_PluginPlugin.h" +#include "../SoundEnginePlugin/Faust_Interpreter_Wwise_PluginSourceFactory.h" + +Faust_Interpreter_Wwise_PluginPlugin::Faust_Interpreter_Wwise_PluginPlugin() +{ +} + +Faust_Interpreter_Wwise_PluginPlugin::~Faust_Interpreter_Wwise_PluginPlugin() +{ +} + +bool Faust_Interpreter_Wwise_PluginPlugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Duration")); + + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(Faust_Interpreter_Wwise_Plugin); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(Faust_Interpreter_Wwise_Plugin); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + Faust_Interpreter_Wwise_Plugin, // Name of the plug-in container for this shared library + Faust_Interpreter_Wwise_PluginPlugin, // Authoring plug-in class to add to the plug-in container + Faust_Interpreter_Wwise_PluginSource // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINEDUMMYASSERTHOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.h new file mode 100644 index 0000000000..5b36bd4ad4 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Faust_Interpreter_Wwise_PluginPlugin.h @@ -0,0 +1,47 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#pragma once + +#include + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=plugin__dll.html +/// for the documentation about Authoring plug-ins +class Faust_Interpreter_Wwise_PluginPlugin final + : public AK::Wwise::Plugin::AudioPlugin +{ +public: + Faust_Interpreter_Wwise_PluginPlugin(); + ~Faust_Interpreter_Wwise_PluginPlugin(); + + /// This function is called by Wwise to obtain parameters that will be written to a bank. + /// Because these can be changed at run-time, the parameter block should stay relatively small. + // Larger data should be put in the Data Block. + bool GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const override; + +}; + +AK_DECLARE_PLUGIN_CONTAINER(Faust_Interpreter_Wwise_Plugin); // Exposes our PluginContainer structure that contains the info for our plugin diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.cpp b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.cpp new file mode 100644 index 0000000000..741f25267a --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.cpp @@ -0,0 +1,795 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ + +#include "Faust_Interpreter_Wwise_PluginPluginGUI.h" +#include "../resource.h" +#include "PluginUtils/syscall.h" +#include "PluginUtils/plugin_utils.h" +#include "AudioInput/audio_inputs.h" +#include +#include +#include +#include + +#define FAUST_DOCS_PAGE L"https://faustdoc.grame.fr/manual/syntax/" + +AK_WWISE_PLUGIN_GUI_WINDOWS_BEGIN_POPULATE_TABLE(PropertyTable) +AK_WWISE_PLUGIN_GUI_WINDOWS_END_POPULATE_TABLE() + +Faust_Interpreter_Wwise_PluginPluginGUI::Faust_Interpreter_Wwise_PluginPluginGUI() + : dspCode(L"") + , faustWnd(nullptr) + , editorWnd(nullptr) + , audioInputCombo(nullptr) + , currAudioInputComboSelection(DEFAUT_AUDIO_INPUT_FOR_EFFECTS) + , pluginWindow(nullptr) + , state(WM_STATE::NONINIT_STATE) + , UnqBuildCompleteWndMsg(RegisterWindowMessage(L"FaustBuildCompleteMessage")) + , fileManager(faustPluginLoader.getExportPath()) +{ + AKPLATFORM::OutputDebugMsg("Faust :: Constructor got called!\n"); +} + +// @TODO create a window warning/info for everything + +Faust_Interpreter_Wwise_PluginPluginGUI::~Faust_Interpreter_Wwise_PluginPluginGUI() +{ + if (pluginWindow) + { + delete pluginWindow; + pluginWindow = nullptr; + } +} + +HINSTANCE Faust_Interpreter_Wwise_PluginPluginGUI::GetResourceHandle() const +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + return AfxGetStaticModuleState()->m_hCurrentResourceHandle; +} + +bool Faust_Interpreter_Wwise_PluginPluginGUI::GetDialog( + AK::Wwise::Plugin::eDialog in_eDialog, + UINT& out_uiDialogID, + AK::Wwise::Plugin::PopulateTableItem*& out_pTable) const +{ + if (in_eDialog == AK::Wwise::Plugin::SettingsDialog) + { + out_uiDialogID = IDD_FAUST_PLUGIN; + out_pTable = PropertyTable; + return true; + } + AKPLATFORM::OutputDebugMsg("Faust :: GetDialog got called!\n"); + return false; +} + +bool Faust_Interpreter_Wwise_PluginPluginGUI::WindowProc( + AK::Wwise::Plugin::eDialog in_eDialog, + HWND in_hWnd, + uint32_t in_message, + WPARAM in_wParam, + LPARAM in_lParam, + LRESULT& out_lResult) +{ + + switch (state) + { + case INIT_STATE: + { + // Sets the code editor when plugin is loaded properly + AKPLATFORM::OutputDebugMsg("Faust :: INIT_STATE got called!\n"); + SetCodeEditorText(); + state = WM_STATE::RUN_STATE; + } + } + + if (in_message == UnqBuildCompleteWndMsg) // UnqBuildCompleteWndMsg is runtime evaluated. Have to be within an if condition instead of being within a case statement. + { + OnBuildCompleted(in_wParam, in_lParam); + return TRUE; + } + + BOOL bRet = FALSE; + switch (in_message) + { + case WM_INITDIALOG: + { + initializeEditor(in_hWnd); + bRet=TRUE; + break; + } + case WM_COMMAND: + { + + int id = LOWORD(in_wParam); + int notify = HIWORD(in_wParam); + + if (notify == BN_CLICKED) + { + if (id == IDC_BUTTON_PREVIEW) + { + OnPreviewButtonClicked(); + } + else if (id == IDC_BUTTON_BUILD) + { + OnBuildButtonClicked(); + } + + else if (id == IDC_NEW_PROJECT_FILE) + { + OnNewProjectFile(); + } + + else if (id == IDC_RENAME_PROJECT_FILE) + { + OnRenameButtonClicked(); + } + + else if (id == IDC_DELETE_PROJECT_FILE) + { + OnDeleteProjectFile(); + } + else if (id == IDC_BUTTON_EXPORT) + { + OnExportClicked(); + } + else if (id == IDC_BUTTON_DOCS) + { + onDocsClicked(); + } + } + else if (notify == CBN_SELCHANGE) + { + if (id == IDC_AUDIO_INPUT_COMBO) + { + int selection = (int)SendMessageW(audioInputCombo, CB_GETCURSEL, 0, 0); + currAudioInputComboSelection = selection; + } + else if (id == IDC_PROJECT_FILES_COMBO) + { + OnProjectFileSelectionChange(); + } + } + bRet = TRUE; + break; + } + case WM_DESTROY: + { + AKPLATFORM::OutputDebugMsg("Faust :: WM_DESTROY got called!\n"); + faustPluginLoader.unloadPlugin(); + SaveCodeEditorText(); + state = WM_STATE::EXIT_STATE; + bRet = TRUE; + break; + } + + } + return bRet; +} + +/* +---------------------------------------------------------------------------------------| +------------------------------------- UI Setup --------------------------------------- | +---------------------------------------------------------------------------------------| +*/ + +void Faust_Interpreter_Wwise_PluginPluginGUI::initializeEditor(HWND in_hWnd) +{ + AKPLATFORM::OutputDebugMsg("Faust :: INITDIALOG got called!\n"); + faustWnd = in_hWnd; + editorWnd = GetDlgItem(faustWnd, IDC_CODE_EDITOR); + audioInputCombo = GetDlgItem(faustWnd, IDC_AUDIO_INPUT_COMBO); + audioInputList audlist = AudioInputs::getAudioInputList(); + for (auto& [id, name] : audlist) + { + SendMessageW(audioInputCombo, CB_ADDSTRING, id, (LPARAM)name); + } + SendMessageW(audioInputCombo, CB_SETCURSEL, currAudioInputComboSelection, 0); + + projectFilesCombo = GetDlgItem(faustWnd, IDC_PROJECT_FILES_COMBO); + newFileButton = GetDlgItem(faustWnd, IDC_NEW_PROJECT_FILE); + renameFileButton = GetDlgItem(faustWnd, IDC_RENAME_PROJECT_FILE); + deleteFileButton = GetDlgItem(faustWnd, IDC_DELETE_PROJECT_FILE); + + int pfid = 0; + std::vector projectFiles = fileManager.getProjectFiles(); + if (projectFiles.size() != 0) + { + for (std::string& name : projectFiles) + { + std::wstring wname = PluginUtils::string2wstring(name); + SendMessageW(projectFilesCombo, CB_ADDSTRING, pfid++, (LPARAM)wname.c_str()); + } + //set default project file selection. + int defaultProjectFile = 0; + SendMessage(projectFilesCombo, CB_SETCURSEL, defaultProjectFile, 0); + currentFileWorkingOn = PluginUtils::string2wstring(projectFiles[defaultProjectFile]); + } + + // for hovering + hToolTip = CreateWindowEx( + 0, TOOLTIPS_CLASS, NULL, WS_POPUP, 0, 0, 0, 0, + faustWnd, + NULL, + GetResourceHandle(), + NULL + ); + AddTooltip(newFileButton, L"Create new Faust dsp file"); + AddTooltip(renameFileButton, L"Rename selected Faust dsp file"); + AddTooltip(deleteFileButton, L"Delete selected Faust dsp file"); + + state = WM_STATE::INIT_STATE; +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::AddTooltip(HWND hTarget, const wchar_t* text) +{ + TOOLINFO ti = { 0 }; + ti.cbSize = sizeof(ti); + ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND; + ti.hwnd = faustWnd; + ti.uId = (UINT_PTR)hTarget; + ti.lpszText = (LPWSTR)text; + + SendMessage(hToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); +} + +/* +---------------------------------------------------------------------------------------| +---------------------------------- Re-usable code ------------------------------------ | +---------------------------------------------------------------------------------------| +*/ + +ProjectFileSelection Faust_Interpreter_Wwise_PluginPluginGUI::getCurrentProjectFileSelection() +{ + int selection = (int)SendMessage(projectFilesCombo, CB_GETCURSEL, 0, 0); + if (selection == CB_ERR){ + return std::make_pair(-1,L""); + } + + wchar_t selectionName[256]; + SendMessage(projectFilesCombo, CB_GETLBTEXT, selection, (LPARAM)selectionName); + return std::make_pair(selection,std::wstring(selectionName)); +} + +bool Faust_Interpreter_Wwise_PluginPluginGUI::SetCodeEditorText() +{ + if (!editorWnd) return false; + + int filesCount = (int)SendMessage(projectFilesCombo, CB_GETCOUNT, 0, 0); + if (!filesCount){ + dspCode.clear(); + } else { + + // get the current project file + auto [option, filename] = getCurrentProjectFileSelection(); + + if (!fileManager.load(PluginUtils::wstring2string(filename), dspCode)) + { + std::wstring message = L"Can't load file " + filename; + ShowSimpleWindow(message.c_str(),L"Error"); + } + } + SetWindowTextW(editorWnd, dspCode.c_str()); + return true; + +} + +bool Faust_Interpreter_Wwise_PluginPluginGUI::SaveCodeEditorText() +{ + int len = GetWindowTextLengthW(editorWnd); + if (len <= 0) + return false; + + // set the dspCode with the existing code written on the editor. + std::wstring buffer(len, L'\0'); + GetWindowTextW(editorWnd, &buffer[0], len + 1); + // ensure null-termination and trim + buffer.resize(wcslen(buffer.c_str())); + dspCode = buffer; + + std::string dspName = PluginUtils::wstring2string(currentFileWorkingOn); + + fileManager.writeFile(dspName, dspCode); + + return true; +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::ShowSimpleWindow(LPCWSTR text, LPCWSTR title) +{ + MessageBoxW(faustWnd, text, title , MB_OK); +} + +/* +---------------------------------------------------------------------------------------| +---------------------------------- Event Handlers ------------------------------------ | +---------------------------------------------------------------------------------------| +*/ + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnBuildCompleted(WPARAM in_wParam, LPARAM in_lParam) +{ + EnableWindow((HWND)in_wParam, TRUE); // re-enable build button after completion + + bool succeeded = (bool)in_lParam; + std::wstring outputMessage; + if (succeeded) + { + outputMessage = L"Plugin Build Successfully!\n" + PluginUtils::string2wstring(buildOutputText); + } else + { + outputMessage = std::wstring(L"Failed to build.\nFor more details check the output log file:\n") + + PluginUtils::string2wstring(buildOutputText); + } + + MessageBoxW(faustWnd, outputMessage.c_str(), L"Faust2Wwise Build Result", MB_OK); + +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnDeleteProjectFile() +{ + int filesCount = (int)SendMessage(projectFilesCombo, CB_GETCOUNT, 0, 0); + if (!filesCount) + { + ShowSimpleWindow(L"Can 't delete no existent file.",L"Warning"); + } + else + { + + auto [sel,deletedName] = getCurrentProjectFileSelection(); + + // delete the projectFile from the combo + SendMessage(projectFilesCombo, CB_DELETESTRING, sel, 0); + + // update projectFile combo + int count = (int)SendMessage(projectFilesCombo, CB_GETCOUNT, 0, 0); + if (count > 0) + { + int newSel = count-1; + SendMessage(projectFilesCombo, CB_SETCURSEL, newSel, 0); + // update currentFileWorkingOn + wchar_t buffer[256]; + SendMessage(projectFilesCombo, CB_GETLBTEXT, newSel, (LPARAM)buffer); + currentFileWorkingOn = buffer; + } + + fileManager.remove(PluginUtils::wstring2string(deletedName)); + } + + // update code editor + SetCodeEditorText(); +} + +bool Faust_Interpreter_Wwise_PluginPluginGUI::OnRenameAccepted(wchar_t *newName) +{ + // get the oldName + auto [sel, oldName] = getCurrentProjectFileSelection(); + + std::string oldNameStr = PluginUtils::wstring2string(oldName); + std::string newNameStr = PluginUtils::wstring2string(std::wstring(newName)); + + // abort if contains spaces... + if (newNameStr.find(' ') != std::string::npos) + { + ShowSimpleWindow(L"Spaces not allowed.", L"Aborting renaming"); + return false; + } + + if (fileManager.rename(oldNameStr, newNameStr)) + { + // 1) rename the comboBox item by: + // ..deleting the old item.. + SendMessage(projectFilesCombo, CB_DELETESTRING, sel, 0); + // ..inserting the new item at the same index .. + SendMessage(projectFilesCombo, CB_INSERTSTRING, sel, (LPARAM)newName); + // .. and selecting the newly inserted item. + SendMessage(projectFilesCombo, CB_SETCURSEL, sel, 0); + // .. + update the currentFileWorkingOn that keeps track of the current selection + currentFileWorkingOn = std::wstring(newName); + + return true; + } + + return false; +} + +LRESULT CALLBACK Faust_Interpreter_Wwise_PluginPluginGUI::onRenameWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_COMMAND: + if (LOWORD(wParam) == RENAME_CANCEL) // OK or Cancel + { + DestroyWindow(hwnd); + return 0; + } + else if (LOWORD(wParam) == RENAME_OK) + { + auto* self = (Faust_Interpreter_Wwise_PluginPluginGUI*) + GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (self) + { + // read the newName + HWND hEdit = GetDlgItem(hwnd, RENAME_EDIT); + wchar_t newName[256]; + GetWindowTextW(hEdit, newName, 256); + + if (wcslen(newName) != 0) // if the text is not empty, and renamed successfully + { + std::string newNameStr = PluginUtils::wstring2string(std::wstring(newName)); + if (!self->fileManager.pfNameUnique(newNameStr)) + { + std::wstring message = newName; + message += L" already exists"; + self->ShowSimpleWindow(message.c_str(), L"Aborting renaming"); + } + else if (!self->OnRenameAccepted(newName)) + { + // unable to rename.. + } + DestroyWindow(hwnd); + break; + } + // else do nothing. Wait for the user to fill up the text. + } + } + break; + + case WM_CLOSE: + DestroyWindow(hwnd); + return 0; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnRenameButtonClicked() +{ + int filesCount = (int)SendMessage(projectFilesCombo, CB_GETCOUNT, 0, 0); + if (!filesCount) + { + ShowSimpleWindow(L"Can 't rename no existent file.",L"Warning"); + return; + } + + HINSTANCE hInst = GetResourceHandle(); + + // Register window class once + static bool registered = false; + if (!registered) + { + WNDCLASSW wc = {}; + wc.lpfnWndProc = onRenameWinProc; + wc.hInstance = hInst; + wc.lpszClassName = L"PopupWinClass"; + RegisterClassW(&wc); + registered = true; + } + + auto [sel,pf] = getCurrentProjectFileSelection(); + std::wstring title = L"Rename " + pf; + + HWND hPopup = CreateWindowExW( + 0, L"PopupWinClass", title.c_str(), + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, + 400, 300, 300, 150, + faustWnd, nullptr, hInst, nullptr); + + CreateWindowExW( + WS_EX_CLIENTEDGE, L"EDIT", L"", + WS_CHILD | WS_VISIBLE, + 20, 30, 240, 25, + hPopup, (HMENU)RENAME_EDIT, hInst, nullptr); + + CreateWindowExW( + 0, L"BUTTON", L"OK", + WS_CHILD | WS_VISIBLE, + 40, 70, 80, 25, + hPopup, (HMENU)RENAME_OK, hInst, nullptr); + + CreateWindowExW( + 0, L"BUTTON", L"Cancel", + WS_CHILD | WS_VISIBLE, + 140, 70, 80, 25, + hPopup, (HMENU)RENAME_CANCEL, hInst, nullptr); + + // pass the pointer to the class (this) to the hPopup window to allow calling of OnRenameAccepted when user presses ok. + SetWindowLongPtr(hPopup, GWLP_USERDATA, (LONG_PTR)this); + + ShowWindow(hPopup, SW_SHOW); +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnNewProjectFile() +{ + // save code + SaveCodeEditorText(); + + std::string newName; + fileManager.create(newName); + std::wstring newPluginName = PluginUtils::string2wstring(newName); + int idx = (int)SendMessage(projectFilesCombo, CB_ADDSTRING, 0, (LPARAM)newPluginName.c_str()); + SendMessage(projectFilesCombo, CB_SETCURSEL, idx, 0); + currentFileWorkingOn = newPluginName; + SetCodeEditorText(); +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnProjectFileSelectionChange() +{ + int sel = (int)SendMessage(projectFilesCombo, CB_GETCURSEL, 0, 0); + if (sel != CB_ERR) + { + SaveCodeEditorText(); + wchar_t buffer[256]; + SendMessage(projectFilesCombo, CB_GETLBTEXT, sel, (LPARAM)buffer); + currentFileWorkingOn = buffer; + SetCodeEditorText(); + } +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnExportClicked() +{ + SaveCodeEditorText(); + + // get the checkbox value + bool saveDSP = (SendMessage(GetDlgItem(faustWnd, IDC_CHECK_SAVE_DSP),BM_GETCHECK, 0, 0) == BST_CHECKED); + + // prompt the user to choose a dir + std::wstring userDir; + int res = AskUserForDirectory(userDir); + + if (res==1) { + ShowSimpleWindow(L"Can 't obtain the export directory to store the files.", L"Export canceled"); + return; + } + else if (res == 0) // store file(s) on SUCCES res + { + std::string filename = PluginUtils::wstring2string(currentFileWorkingOn); + std::string storeDir = PluginUtils::wstring2string(userDir) + '/' + filename; + std::filesystem::create_directory( std::filesystem::path(storeDir)); + + // export cpp + std::string cppfilePath = storeDir + '/' + filename + ".cpp"; + bool doublePrecision = (SendMessage(GetDlgItem(faustWnd,IDC_CHECK_DOUBLE_PRECISION),BM_GETCHECK, 0, 0) == BST_CHECKED); + std::string errorMessage; + bool cppExported = faustPluginLoader.exportCPP( + filename, + PluginUtils::wstring2string(dspCode), + cppfilePath, + doublePrecision, + errorMessage + ); + + // export dsp + bool dspExported=true; + if (saveDSP) + { + std::string dspfilePath = storeDir + '/' + filename + ".dsp"; + dspExported = PluginUtils::store_utf16_file(dspfilePath, dspCode); + } + + // show windows + std::string msg, title; + + if (!cppExported) { + msg = "Could not export cpp file.\n" + errorMessage; + title = "Export error"; + } + if (saveDSP && !dspExported) { + msg+="\nCould not export dsp file."; + title = "Export error"; + } + if (cppExported && dspExported) + { + title = "Export success"; + msg = "Successfully exported cpp file"; + if (saveDSP) { + msg += "\nSuccessfully exported dsp file."; + } + std::string dirMsg = "\nOutput dir : " + storeDir; + msg+=dirMsg; + } + ShowSimpleWindow(PluginUtils::string2wstring(msg).c_str(), PluginUtils::string2wstring(title).c_str()); + } +} + +int Faust_Interpreter_Wwise_PluginPluginGUI::AskUserForDirectory(std::wstring& directory) +{ + IFileDialog* pfd = nullptr; + HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&pfd)); + + if (FAILED(hr)) + { + return 1; + } + + DWORD options; + pfd->GetOptions(&options); + pfd->SetOptions(options | FOS_PICKFOLDERS); + + hr = pfd->Show(faustWnd); // parent window + if (FAILED(hr)) { + pfd->Release(); + return 2; // cancelled + } + + IShellItem* pItem = nullptr; + hr = pfd->GetResult(&pItem); + if (FAILED(hr)) { + pfd->Release(); + return 1; // failed + } + + PWSTR path = nullptr; + hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &path); + + if (SUCCEEDED(hr)) + { + directory = path; + } + + CoTaskMemFree(path); + pItem->Release(); + pfd->Release(); + + return 0; +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::onDocsClicked() +{ + ShellExecuteW( + faustWnd, + L"open", + std::wstring(FAUST_DOCS_PAGE).c_str(), + NULL, + NULL, + SW_SHOWNORMAL + ); +} + +/* +---------------------------------------------------------------------------------------| +----------------------------- Async Build and Preview -------------------------------- | +---------------------------------------------------------------------------------------| +*/ + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnPreviewButtonClicked() +{ + // Important: this function runs asynchronously. + + SaveCodeEditorText(); + + PluginState pluginState = faustPluginLoader.getPluginState(); + if ( pluginState != PluginState::READY) + { + + // build plugin asynchronously + std::thread([this]() { + + std::string errorMsg; + bool pluginCreated = faustPluginLoader.createPlugin( + PluginUtils::wstring2string(this->dspCode), + currAudioInputComboSelection, + errorMsg + ); + + if (!pluginCreated) + { + std::wstring outputMessage = std::wstring(L"Failed to compile dsp file.\nError message:\n") + + PluginUtils::string2wstring(errorMsg); + ShowSimpleWindow(outputMessage.c_str(),L"Preview error"); + return; + } + + // disable selection of audio input source for the effect plugins when preview. + EnableWindow(audioInputCombo, FALSE); + + ParameterList ¶meters = faustPluginLoader.getParameters(); + PluginConfiguration& cfg = faustPluginLoader.getConfiguration(); + PluginState pluginState = faustPluginLoader.getPluginState(); + + // verify that params are obtained... + if (parameters.empty()) + { + ShowSimpleWindow( + L"The DSP code does not define any parameters. Simply press \'Play\' to start playback", + PluginUtils::string2wstring( cfg.plugin_name ).c_str() + ); + + while(pluginState==PluginState::PLUGIN_SET || pluginState==PluginState::READY) + { + pluginState = faustPluginLoader.getPluginState(); + } + } + else + { + pluginWindow = new PluginWindow(faustWnd,cfg,parameters); + if (pluginWindow->isWindowCreated()) + { + pluginWindow->Show(); + pluginState = faustPluginLoader.getPluginState(); + while + ( + (pluginState==PluginState::PLUGIN_SET || pluginState==PluginState::READY) + && pluginWindow + && pluginWindow->isActive() + ) + { + pluginWindow->Update(); + pluginState = faustPluginLoader.getPluginState(); + } + // close PluginWindow and reset plugin + if (pluginWindow){ + delete pluginWindow; + pluginWindow = nullptr; + faustPluginLoader.resetPlugin(); + } + } + } + + // re-enable the audio Input combo + EnableWindow(audioInputCombo, TRUE); + + }).detach(); + + } + +} + +void Faust_Interpreter_Wwise_PluginPluginGUI::OnBuildButtonClicked(){ + + SaveCodeEditorText(); + + HWND buildButton = GetDlgItem(faustWnd, IDC_BUTTON_BUILD); + EnableWindow(buildButton, FALSE); // disable build button... + + std::thread([this, buildButton]() + { + // compile using faust2wwise implementation.. + auto [id,pluginName] = getCurrentProjectFileSelection(); + bool doublePrecision = (SendMessage(GetDlgItem(faustWnd,IDC_CHECK_DOUBLE_PRECISION),BM_GETCHECK, 0, 0) == BST_CHECKED); + bool isOutOfPlace = (SendMessage(GetDlgItem(faustWnd,IDC_CHECK_OUT_OF_PLACE),BM_GETCHECK, 0, 0) == BST_CHECKED); + bool res = faustPluginLoader.buildPlugin(PluginUtils::wstring2string(pluginName), + PluginUtils::wstring2string(dspCode), + doublePrecision, + isOutOfPlace, + buildOutputText); + + // temp log message + char dbg[256]; + snprintf(dbg, 256, "OnBuildButtonClicked: result is %d", res); + AKPLATFORM::OutputDebugMsg(dbg); + + // notify GUI thread - re-enabling the button will happen after the message is received within winProc function. + PostMessage(faustWnd, UnqBuildCompleteWndMsg, (WPARAM)buildButton, (LPARAM)res); + + //@TODO Design a way to allow user to inspect the output of the build (errors/warnings/success etc..) + + }).detach(); + +} + +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( + Faust_Interpreter_Wwise_Plugin, // Name of the plug-in container for this shared library + Faust_Interpreter_Wwise_PluginPluginGUI, // Authoring plug-in class to add to the plug-in container + Faust_Interpreter_Wwise_PluginSource // Corresponding Sound Engine plug-in class +); diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.h new file mode 100644 index 0000000000..402efd691f --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/Win32/Faust_Interpreter_Wwise_PluginPluginGUI.h @@ -0,0 +1,120 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2025 Audiokinetic Inc. +*******************************************************************************/ +#pragma once + +#include "../Faust_Interpreter_Wwise_PluginPlugin.h" +#include "plugin_loader.h" +#include "PluginTemplate/UI/plugin_window.h" +#include "ProjectFiles/Manager.h" + +typedef std::pair ProjectFileSelection; + +enum WM_STATE{ + INIT_STATE=1, + RUN_STATE=2, + EXIT_STATE=3, + NONINIT_STATE=0 +}; + +class Faust_Interpreter_Wwise_PluginPluginGUI final + : public AK::Wwise::Plugin::PluginMFCWindows<> + , public AK::Wwise::Plugin::GUIWindows +{ +public: + Faust_Interpreter_Wwise_PluginPluginGUI(); + ~Faust_Interpreter_Wwise_PluginPluginGUI(); + + HINSTANCE GetResourceHandle() const override; + + bool GetDialog( + AK::Wwise::Plugin::eDialog in_eDialog, + UINT& out_uiDialogID, + AK::Wwise::Plugin::PopulateTableItem*& out_pTable + ) const override; + + bool WindowProc( + AK::Wwise::Plugin::eDialog in_eDialog, + HWND in_hWnd, + uint32_t in_message, + WPARAM in_wParam, + LPARAM in_lParam, + LRESULT& out_lResult) override; + +private: + + HWND faustWnd, + editorWnd, + audioInputCombo, + projectFilesCombo, + newFileButton, + renameFileButton, + deleteFileButton , + renameEdit, + hToolTip; + + // HINT: PluginLoader is a singleton. + PluginLoader& faustPluginLoader = PluginLoader::getInstance(); + PluginWindow* pluginWindow; + ProjectFilesManager fileManager; + + std::wstring dspCode; + + // used to store the state of specific buttons + WM_STATE state; // used to set the code editor after the plugin initializations is completed. + int currAudioInputComboSelection; + std::wstring currentFileWorkingOn; + + // used for async building of plugin + UINT UnqBuildCompleteWndMsg; + std::string buildOutputText; + + // UI setup + void initializeEditor(HWND); + void AddTooltip(HWND, const wchar_t*); + + // Re-usable code + ProjectFileSelection getCurrentProjectFileSelection(); + bool SetCodeEditorText(); + bool SaveCodeEditorText(); + void ShowSimpleWindow(LPCWSTR, LPCWSTR); + + // Event handlers + void OnBuildCompleted(WPARAM, LPARAM); + void OnDeleteProjectFile(); + void OnRenameButtonClicked(); + bool OnRenameAccepted(wchar_t*); + static LRESULT CALLBACK onRenameWinProc(HWND, UINT, WPARAM, LPARAM); + void OnNewProjectFile(); + void OnProjectFileSelectionChange(); + void OnExportClicked(); + int AskUserForDirectory(std::wstring&); + void onDocsClicked(); + + // Async Build and Preview + void OnPreviewButtonClicked(); + void OnBuildButtonClicked(); // @TODO: requires admin priviledges. Check if can be given on runtime for this specific operation. + +}; \ No newline at end of file diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/en/Duration.md b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/en/Duration.md new file mode 100644 index 0000000000..866c85a54d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/en/Duration.md @@ -0,0 +1,7 @@ +## Placeholder Parameter + +The description of what this parameter does. + +**Note**: Additional note goes here. + +Units: x
diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ja/Duration.md b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ja/Duration.md new file mode 100644 index 0000000000..4c53a60d90 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ja/Duration.md @@ -0,0 +1,7 @@ +## プレースホルダパラメータ + +このパラメータの機能の説明。 + +**注**:ここに追加のメモが記載されます。 + +単位:x
diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ko/Duration.md b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ko/Duration.md new file mode 100644 index 0000000000..a3c9345793 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/ko/Duration.md @@ -0,0 +1,7 @@ +## 자리 표시자 매개 변수 + +이 매개 변수에 대한 설명 + +**참고** : 추가 메모가 여기에 옵니다. + +단위 : x
diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/zh/Duration.md b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/zh/Duration.md new file mode 100644 index 0000000000..3705c09bf9 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/res/Md/zh/Duration.md @@ -0,0 +1,7 @@ +## 占位符参数 + +该参数的功能说明。 + +**注意**: 这部分为附加说明 。 + +单位:x
diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/resource.h b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/resource.h new file mode 100644 index 0000000000..d4fe151e95 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/WwisePlugin/resource.h @@ -0,0 +1,23 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +#define IDD_FAUST_PLUGIN 101 +#define IDC_CODE_EDITOR 1001 +#define IDC_BUTTON_PREVIEW 1002 +#define IDC_BUTTON_BUILD 1003 +#define IDC_AUDIO_INPUT_COMBO 1004 +#define IDC_PROJECT_FILES_COMBO 1005 +#define IDC_NEW_PROJECT_FILE 1006 +#define IDC_RENAME_PROJECT_FILE 1007 +#define IDC_DELETE_PROJECT_FILE 1008 +#define RENAME_EDIT 1009 +#define RENAME_OK 1010 +#define RENAME_CANCEL 1011 +#define IDC_BUTTON_EXPORT 1012 +#define IDC_CHECK_SAVE_DSP 1013 +#define IDC_BUTTON_DOCS 1014 +#define IDC_CHECK_DOUBLE_PRECISION 1015 +#define IDC_CHECK_OUT_OF_PLACE 1016 + +#endif // RESOURCE_H + diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/additional_artifacts.json b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/additional_artifacts.json new file mode 100644 index 0000000000..25f28d606d --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/additional_artifacts.json @@ -0,0 +1,27 @@ +// See https://www.audiokinetic.com/library/edge/?source=SDK&id=effectplugin_tools.html#effect_plugin_tools_packaging_additional_files +// for the documentation about the additional_artifacts.json format +{ + // List of additional files to package for the Authoring platform + "Authoring": [ + { + // The files in the Help folder located at the root of the plug-in directory + // will be packaged so that they are installed in the Authoring/Help/Faust_Interpreter_Wwise_Plugin folder + // of a Wwise installation + "Authoring/Help/Faust_Interpreter_Wwise_Plugin": ["Help/*"], + // Similarly for the files in the FactoryAssets folder + "Authoring/Data/Factory Assets/Faust_Interpreter_Wwise_Plugin": ["FactoryAssets/*"] + } + ] + + // List of additional files to package for the platform + // "": [ + // // Each entry is either: + // // - A path relative to the root of your Wwise installation (can contain glob patterns); + // // - A destination -> sources object where the destination is a path relative to the root + // // of your Wwise installation and the sources are paths relative to the root of the + // // plug-in directory (can contain glob patterns). + // string | { string: [string] }, + // ... + // ], + // ... +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/bundle_template.json b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/bundle_template.json new file mode 100644 index 0000000000..5d93373af8 --- /dev/null +++ b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/bundle_template.json @@ -0,0 +1,79 @@ +// See https://www.audiokinetic.com/library/edge/?source=SDK&id=plugin__packaging.html#plugin_packaging_bundle_metadata +// for the documentation about the bundle_template.json format +{ + // Unique identifier of this bundle. Id must be unique across all existing plugins and versions. + "id": "Paschalis Melissas.Faust_Interpreter_Wwise_Plugin.${year}_${major}_${minor}_${build}", + + // Name displayed in the Wwise Launcher for this bundle + "name": "Faust_Interpreter_Wwise_Plugin", + + // Tag uniquely identifying the plug-in (format [0-9A-z_]+, 50 characters maximum) + "tag": "Faust_Interpreter_Wwise_Plugin", + + // Description displayed in the Wwise Launcher for this bundle + "description": "Embedded Faust Interpreter as a Wwise Source Plugin ", + + // Vendor name displayed in the Wwise Launcher for this bundle + "vendor": "Paschalis Melissas", + + // Base64 representation of an image to be displayed in the Wwise Launcher for this bundle (PNG, JPEG or GIF) + "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", + + // Type of this bundle, must be "plugin" + "type": "plugin", + + // Data that is specific to this bundle type + "productDependentData": { + "targetWwiseVersion": { + "year": ${year}, + "major": ${major} + } + }, + + // Version of this bundle + "version": { + "year": ${year}, + "major": ${major}, + "minor": ${minor}, + "build": ${build} + }, + + // List of EULAs associated with this bundle + "eulas": [ + // { + // "displayName": string, // Name displayed in the Wwise Launcher for this EULA + // "displayContent": string, // Text displayed in the Wwise Launcher for this EULA + // "id": string // Unique identifier of this EULA + // }, + // ... + ], + + // Labels displayed next to this bundle + "labels": [ + // { + // "class": string, // Style class applied to this label (default, primary, success, info, warning, danger) + // "displayName": string // Name displayed in the Wwise Launcher for this label + // }, + // ... + ], + + // Online documentation links for this bundle + "links": [ + // { + // "displayName": string, // Name displayed in the Wwise Launcher for this link + // "id": string, // Unique identifier of this link + // "url": string // Target URL of this link + // }, + // ... + ], + + // Local documentation files for this bundle + "documentation": [ + // { + // "displayName": string, // Name displayed in the Wwise Launcher for this documentation file + // "filePath": string, // Path to the documentation file + // "language": "en" | "ja" | "zh" // Language of the documentation file + // }, + // ... + ] +} diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/faust_interpr_wwise_plugin_screenshot.PNG b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/faust_interpr_wwise_plugin_screenshot.PNG new file mode 100644 index 0000000000..c84fb3e86d Binary files /dev/null and b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/faust_interpr_wwise_plugin_screenshot.PNG differ diff --git a/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/set_wwise_root_img.png b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/set_wwise_root_img.png new file mode 100644 index 0000000000..8074a0e27a Binary files /dev/null and b/architecture/wwise/Faust_Interpreter_Wwise_Plugin/extras/set_wwise_root_img.png differ diff --git a/architecture/wwise/README.md b/architecture/wwise/README.md index e16a5f9682..67b39f5460 100644 --- a/architecture/wwise/README.md +++ b/architecture/wwise/README.md @@ -1,12 +1,19 @@ -# `faust2wwise` static compilation tool +# `faust2wwise` static compilation tool and dynamic compilation plugin + +#### Static command-line tool `faust2wwise` is a command-line tool that generates AudioKinetic Wwise plugins from Faust DSP code. It bridges the gap between the FAUST functional DSP programming language and Wwise’s audio middleware, supporting both **Source** and **Effect** (in-place and out-of-place) plugins. +#### Dynamic compilation plugin + +Additionally, `faust2wwise` ships with the `Faust Interpreter Wwise Plugin`, a Wwise Authoring plugin that provides an integrated dynamic compilation tool that wraps the faust interpreter and provides a code editor to convert Faust DSP code into Wwise plugins, directly throughout the Wwise enviroment. For more details, refer to the [Faust Interpreter Wwise Plugin](Faust_Interpreter_Wwise_Plugin/README.md) page. + ## Description Following the `faust2xxx` model, Faust-compiled code is integrated into Wwise using the `wp` script and template files provided by the Wwise SDK, along with a patch-based Python method for plugin generation. -Supported platforms include Windows, MSYS2, and macOS (via implicit support for the Sound Engine portion only). +Supported **host platforms** include Windows, MSYS2, and macOS (via implicit support for the Sound Engine portion only). +Supported **target platforms** include Windows, macOS and Android.These are the platforms for which Wwise plugins can be generated. ## Supported Features @@ -18,6 +25,10 @@ Supported platforms include Windows, MSYS2, and macOS (via implicit support for - Error handling - Testing script to validate against all Faust example files - Support for channel mask selection for explicit speaker configuration +- Support for Faust effects with mismatched numbers of input and output channels (see the important note in the [in-place vs out-of-place chapter](#in-place-vs-out-of-place-and-channel-setup-effect-plugins-only)). + +(i.e. for [examples/SAM/chorus/chorus.dsp](../../examples/SAM/chorus/chorus.dsp)). + ## Pipeline overview @@ -54,7 +65,8 @@ The way this work is orchestrated follows a multi-step process, where each phase `faust2wwise` comes with the following requirements: - **FAUST** - The `Faust` compiler must be available in your system **PATH**. -- **Wwise SDK (>=2024.1.0)** +- **Wwise SDK (Versions >=2024 and <=2026)** + - make sure Wwise dependencies are installed (see [Windows-Specific Information](https://www.audiokinetic.com/en/public-library/2025.1.9_9197/?source=SDK&id=windows_specificinfo.html), [Mac-Specific Information](https://www.audiokinetic.com/en/public-library/2025.1.9_9197/?source=SDK&id=mac_specificinfo.html) or [Android-Specific Information](https://www.audiokinetic.com/en/public-library/2025.1.9_9197/?source=SDK&id=android_specificinfo.html), as enlisted in **Release Notes**, under **{Platform} {Wwise-Version}** page. For instance, for the Wwise `2024.1.12` version, see [Windows Release Notes --> Windows 2024.1.12](https://www.audiokinetic.com/en/public-library/2025.1.9_9197/?source=SDK&id=windows_releasenotes_2024_1_12.html). - `WWISEROOT` must also be exposed system-wide. - **Python (>=3.9)** - **Console access with admin rights** @@ -97,6 +109,39 @@ faust2wwise myfilter.dsp -double --out-of-place *Type `faust2wwise --help` to view all the available command-line options.* +### Specifying target platform and architecture targets (and toolsets) + +Building Wwise projects through `faust2wwise` is automatically configured for **Windows** and **MacOS** using predefined default settings based on the host operating system. This behaviour is implemented for convenience, when the host platform is the same with the target platform, allowing rapid conversions in a non cross-compilation setting. + +However, passing explicit arguments is recommended, especially for custom builds, or when targeting a specific compiler toolset, architecture, or platform. + +For example, the following commands all build an **Authoring** plugin on Windows: + +``` +# using default settings +faust2wwise myFaustEffect.dsp +# using explicit arguments for Visual Studio 2022 (default on Windows) +faust2wwise myFaustEffect.dsp Authoring --toolset vc170 --arch x64 +# using explicit arguments for Visual Studio 2019 +faust2wwise myFaustEffect.dsp Authoring --toolset vc160 --arch x64 +``` + +Similarly, building for Android without specifying an architecture: + +``` +faust2wwise myFaustEffect.dsp --platform Android +``` + +... builds the Wwise project for all supported Android target architectures (armeabi-v7a, x86, arm64-v8a, x86_64). + +To build only for a specific Android architecture (i.e. for arm64-v8a): + +``` +faust2wwise myFaustEffect.dsp --platform Android --arch arm64-v8a +``` + +*Type `faust2wwise --help` to view all the available command-line options.* + ### Plugin Naming By default, the plugin name is derived from the file name of the dsp file. If the filename begins with a number, the prefix `Dsp_` is automatically added. @@ -154,6 +199,29 @@ faust2wwise myGenerator.dsp --spkcfg AK_SPEAKER_SETUP_5POINT1 ``` This example shows of how explicit speaker configuration can be provided for a Faust DSP file that generates audio output for 6 channels. +### In-place vs out-of-place and channel setup (Effect plugins only) + +For effect plugins, you may explicitly specify the buffer interface you would like to use. Additional information can be found in the [Faust docs]() and the [Wwise docs](). + +**Example:** + +For **in-place** buffer configuration, where the same buffer is used for both Faust inputs and outputs, you may use the `--in-place` flag, use the `--in-place` flag, or omit the flag completely (this is the default behaviour). + +``` +faust2wwise myEffect.dsp +faust2wwise myEffect2.dsp --in-place +``` + +For an **out-of-place** buffer configuration, where separate buffers are used for Faust inputs and outputs, use the `--out-of-place` flag explicitly. + +``` +faust2wwise myEffect.dsp --out-of-place +``` + +> Important note + +The Wwise backend handles Faust channels channel-wise: missing input channels are filled with silence and additional output channels are allocated as needed. No channel mixing or duplication is performed. If an in-place effect is requested, it is automatically generated as an out-of-place effect, since Wwise in-place effects require identical input and output channel counts. + ## Testing To test `faust2wwise`, a Python test script is provided that runs the conversion script on all `.dsp` files in a given directory. To use it, run `faust2wwise` in test mode using the `test` command-line parameter: @@ -170,7 +238,7 @@ Test results are stored in the current working directory under the `myF2Wtests/` > Important: Because `faust2wwise test` make system calls that attempt to access environmental variables that require admin rights and also installs or uninstalls plugins in system-level Wwise directories, it must be run from a console with **administrative rights**. -> Note: Testing on **macOS** is possible but not supported out-of-the-box due to Wwise Authoring plug-in constraints. Running `faust2wwise` requires building parts of the plug-in on Windows and manually copying files between platforms. Additionally, the`--clean` option is currently not supported on **macOS**, as the installation directory cannot be reliably determined. For more details, refer to the [Limitations](#limitations) section on macOS support. +> Note: Testing on **macOS** is possible but not supported out-of-the-box due to Wwise Authoring plug-in constraints. Running `faust2wwise` requires building parts of the plug-in on Windows and manually copying files between host platforms. Additionally, the`--clean` option is currently not supported on **macOS**, as the installation directory cannot be reliably determined. For more details, refer to the [Limitations](#limitations) section on macOS support. **Compiling Faust examples from the official Faust repo** @@ -222,15 +290,7 @@ This is a common error and it typically means that the DSP file has already been
fatal error: faust/dsp/dsp.h file not found
-This error is observed on macOS platform and usually occurs when the Faust include path is misconfigured—most often, the leading / is missing (e.g., usr/local/include instead of /usr/local/include), causing the compiler to fail. To fix this, open the project in Xcode, go to Build Settings -> Search Paths -> Header Search Paths, and manually correct the path by ensuring it begins with a /. Then continue building the plugin using Xcode. -
- -
- -
-Cannot use throw with exceptions disabled -
-This error occurs on macOS when building with Xcode and using throw in the code, while C++ exceptions are disabled. To fix this, open the project in Xcode, navigate to Build Settings -> Apple Clang -> Language - C++ -> Enable C++ Exceptions, and set to Yes. Then continue building the plugin using Xcode. +This error is observed on macOS host platform and usually occurs when the Faust include path is misconfigured—most often, the leading / is missing (e.g., usr/local/include instead of /usr/local/include), causing the compiler to fail. To fix this, open the project in Xcode, go to Build Settings -> Search Paths -> Header Search Paths, and manually correct the path by ensuring it begins with a /. Then continue building the plugin using Xcode.

diff --git a/architecture/wwise/config.py b/architecture/wwise/config.py index adaef5b745..4247f24e76 100644 --- a/architecture/wwise/config.py +++ b/architecture/wwise/config.py @@ -35,6 +35,7 @@ class Config: wwiseroot: Final[str] wp_script: Final[str] cfgJsonFileName: Final[str] + SUCCESS_EXIT_CODE: Final[int] ERR_INVALID_INPUT: Final[int] ERR_ENVIRONMENT: Final[int] ERR_FAUST_COMPILE: Final[int] @@ -66,9 +67,16 @@ def __init__(self, wwiseroot , faust_dsp_dir, faust_include_dir) -> None : # Wwise paths self.wwiseroot = wwiseroot # Root dir of the Wwise installation self.wp_script = os.path.join(self.wwiseroot, 'Scripts', 'Build', 'Plugins', 'wp.py') - self.patch_version = str(wwiseroot).split("Wwise")[1][:4] # Derived from wwise version and used for defining the wwise_template_dir + # self.patch_version = str(wwiseroot).split("Wwise")[1][:4] # Derived from wwise version and used for defining the wwise_template_dir + self.patch_version = str(wwiseroot).split("Wwise")[1].lstrip("_")[:4] # .lstrip("_") only for testing releases marked as "NOT FOR PRODUCTION", where the WWISEROOT dir is named with an intermediate underscore( _ ), i.e. Wwise_2026.1.2.9249 self.wwise_template_dir = None # Directory where the template files are stored - self.supportedWwiseVersions = ["2024"] # TODO Expand this on future development that enable support for previous/later Wwise versions + # Project paths + self.build_location = None + self.install_location = None + # Wwise versioning and cross compilation support + self.supportedWwiseVersions = ["2024", "2025", "2026"] # TODO Expand this on future development that enable support for previous/later Wwise versions + self.crossCompilationSupportedPlatforms = ["Android"] # TODO Expand this on future development to enable support for other target platforms (Sony, Nintendo, Mac on Windows etc.) + self.crossCompilationEnabled = False # temp path self.temp_dir = "_temp_" # Temp dir to store temp data ( i.e. jsonfile ) @@ -84,6 +92,7 @@ def __init__(self, wwiseroot , faust_dsp_dir, faust_include_dir) -> None : self.wwise_platform = None self.wwise_plugin_interface = None self.wwise_toolset = None + self.wwise_with_test_project = "none" # avail in Wwise >= 2025 self.wwise_debugger = False self.wwise_disable_codesign = False self.wwise_configuration = "Release" # default @@ -147,9 +156,12 @@ def print(self) -> None : print(f"output_dir {self.output_dir}") print(f"faust_options {self.faust_options}") print("Wwise params:") + print(f"cross_compilation_enabled {self.crossCompilationEnabled}") print(f"platform {self.wwise_platform}") if self.wwise_toolset: print(f"toolset {self.wwise_toolset}") + if self.patch_version in ["2025", "2026"]: + print(f"with_test_project {self.wwise_with_test_project}") if self.wwise_debugger: print(f"debugger {self.wwise_debugger}") if self.wwise_disable_codesign: @@ -202,11 +214,13 @@ def print_summary(self) -> None: print("=====================================") print("Faust2Wwise conversion completed!") print(f"Generated plugin: {self.plugin_name}") - print(f"Plugin type: {self.plugin_type}" + (" (in-place)" if self.plugin_type == "effect" and self.wwise_plugin_interface=="in-place" else " (out-of-place)" if self.plugin_type == "effect" else "")) + print(f"Plugin type: {self.plugin_type}" + (f" ({self.wwise_plugin_interface})" if self.plugin_type == "effect" else "")) print(f"IO: num inputs({self.num_inputs}), num outputs({self.num_outputs})") - print(f"Build Location: {os.path.join(self.output_dir, self.plugin_name)}") + print(f"Build location: {self.build_location}") + if self.wwise_with_test_project: + print(f"Test project location: {os.path.join(self.build_location, 'SoundEnginePluginTest')}") print(f"Configuration file: {self.cfg_json_path}") - print(f"Installation: {os.path.join(self.wwiseroot, 'Authoring', self.wwise_arch, self.wwise_configuration, 'bin', 'Plugins', self.plugin_name)}.(ext)") + print(f"Install location: {self.install_location}") print("=====================================") print("") @@ -234,6 +248,8 @@ def to_json(self) -> None: """Stores the configuration into a JSON file within ${self.output_dir} directory. """ + wwise_arch = "[armeabi-v7a, x86, arm64-v8a, x86_64]" if (self.wwise_platform == "Android" and self.wwise_arch is None) else self.wwise_arch + config_dict = { "Paths": { "Faust": { @@ -262,10 +278,11 @@ def to_json(self) -> None: "Wwise": { "platform": self.wwise_platform, "toolset": self.wwise_toolset, + "with_test_project": self.wwise_with_test_project, "debugger": self.wwise_debugger, "disable_codesign": self.wwise_disable_codesign, "configuration": self.wwise_configuration, - "arch": self.wwise_arch, + "arch": wwise_arch, "build_hooks_file": self.wwise_build_hooks_file, "toolchain_vers": self.wwise_toolchain_vers, "toolchain_env_script": self.wwise_toolchain_env_script, @@ -305,19 +322,16 @@ def to_json(self) -> None: "num_inputs": self.num_inputs, "num_outputs": self.num_outputs }, - "location": os.path.join(self.output_dir, self.plugin_name), - "installation": os.path.join( - self.wwiseroot, - 'Authoring', - self.wwise_arch, - self.wwise_configuration, - 'bin', - 'Plugins', - self.plugin_name - ) + ".(ext)" + "Build location": self.build_location, + "Install location": self.install_location } } + if self.wwise_with_test_project: + config_dict["Summary"].update({ + "Test project location": os.path.join(self.build_location, 'SoundEnginePluginTest') + }) + with open(self.cfg_json_path, 'w', encoding='utf-8') as f: json.dump(config_dict, f, indent=4) print(f"OK: Configuration successfully saved to: {self.cfg_json_path}") \ No newline at end of file diff --git a/architecture/wwise/faustinterpreter.py b/architecture/wwise/faustinterpreter.py new file mode 100644 index 0000000000..8834146096 --- /dev/null +++ b/architecture/wwise/faustinterpreter.py @@ -0,0 +1,138 @@ + +from html import parser +import os +import sys +from pathlib import Path +import config +import utils +import argparse +from typing import List, Optional + +DEFAULT_TOOLSET = "vc170" + +class PluginInstaller: + + def __init__(self, wwiseroot:Path , faust_dsp_dir:Path, faust_include_dir:Path): + + self.cfg = config.Config(wwiseroot , faust_dsp_dir, faust_include_dir) + + def setup_environment(self) -> None: + """ + Sets up environment, for installing the Faust interpreter as a Wwise plugin,including the following steps: + - parse arguments, + - initialize uninitialized configuration variables, + + Args: + args(List[str]): Optional list of arguments. If not provided, parse_arguments function makes + use of sys library to retrieve them. + """ + + if self.cfg.patch_version not in self.cfg.supportedWwiseVersions: + sys.stderr.write(f"Unsupported Wwise version : {self.patch_version}. \ + Available Wwise (major) versions: {self.supportedWwiseVersions}") + sys.exit(self.ERR_ENVIRONMENT) + + self._parse_arguments() + + # setup before installation + self.cfg.plugin_name = "Faust_Interpreter_Wwise_Plugin" + self.cfg.wwise_platform = "Authoring" + self.cfg.build_location = os.path.join(self.cfg.faust_dsp_dir, "wwise", self.cfg.plugin_name) + self.cfg.plugin_type = "source" + self.cfg.cfg_json_path = None + self.cfg.install_location = utils.get_installation_location(self.cfg) + + # ========================================================================= + # SETUP ENVIRONMENT + # ========================================================================= + def _print_usage(self) -> None: + """ + Prints usage information for the `faust2wwise interpreter-install` subcommand. + """ + print("Install the Faust interpreter as a Wwise plugin.") + print("Usage:") + print("faust2wwise interpreter-install [options]") + print("") + print("Platform: Windows with Wwise SDK") + print("") + print("Requirements: Wwise SDK, Faust compiler, Python") + print("") + print("Options:") + print(" -h, --help Show this help message") + print(" --toolset toolset used to build on Windows platforms (vc160, vc170).") + # print(" --configuration configuration to build (Debug, Release, Profile,...).") # TODO + print(" --arch architecture to build (x32, x64, ...).") + sys.exit(self.cfg.SUCCESS_EXIT_CODE) + + def _parse_arguments(self) -> argparse.Namespace: + """ + Parses command-line arguments dedicated to the Faust Interpreter Wwise plugin installlation, + making use of the configuration object that is used in the faust2wwise cli tool. + + The only args that are used are the : + - Wwise-related arguments (arch, toolset, configuration, etc.) + + Args: + cfg (Config): The configuration object to populate. + args (List[str], optional): Command-line argument list (used for testing). Defaults to sys.argv[1:]. + + Returns: + parsed_args : the parsed arguments. + """ + + sys.argv.remove('interpreter-install') + + parser = argparse.ArgumentParser(description="Converts Faust DSP files to Wwise plugins", + add_help=False) + parser.add_argument('-h', '--help', action='store_true', help='Show help message') + parser.add_argument('--toolset', help='toolset used to build on Windows platforms (vc160, vc170).') + # parser.add_argument('--configuration', help='configuration to build (Debug, Release, Profile,...).') # TODO + parser.add_argument('--arch', help='architecture to build (x32, x64, ...).') + + args = sys.argv[1:] + parsed_args = parser.parse_args(args) + + if parsed_args.help: + self._print_usage() + + #TODO : add configuration argument parsing and handling + # if parsed_args.configuration: + # self.cfg.wwise_configuration = parsed_args.configuration + self.cfg.wwise_arch = parsed_args.arch or utils.detect_arch(self.cfg) + self.cfg.wwise_toolset = parsed_args.toolset or DEFAULT_TOOLSET + + # ========================================================================= + # INSTALL FAUST INTERPRETER AS A WWISE PLUGIN + # ========================================================================= + + def install_interpreter(self) -> None: + + """Installs the Faust interpreter as a Wwise plugin.""" + + print("------------------------------------------Installing the Faust interpreter as a Wwise plugin...") + + self.setup_environment() + + # Entering project directory + os.chdir(self.cfg.build_location) + + # Running premake + utils.run_system_command( + ["python", + self.cfg.wp_script, + "premake", self.cfg.wwise_platform], + error_code=self.cfg.ERR_CONFIGURATION) + + # Building and installing the Faust interpreter + utils.run_system_command( + ["python", + self.cfg.wp_script, + "build", self.cfg.wwise_platform, + "-x", self.cfg.wwise_arch, + "-t", self.cfg.wwise_toolset, + "-c", self.cfg.wwise_configuration], + error_code=self.cfg.ERR_BUILD) + + print("OK : Faust interpreter plugin installed successfully!") + + self.cfg.print_summary() \ No newline at end of file diff --git a/architecture/wwise/integrator.py b/architecture/wwise/integrator.py index 463c5be4af..5c7fb7fe2b 100644 --- a/architecture/wwise/integrator.py +++ b/architecture/wwise/integrator.py @@ -201,6 +201,7 @@ def replace_custom_templates(cfg) -> None: print(f"OK : Replaced: {target} with {template}") else: print(f"ERROR: Template file not found: {template_path}") + sys.exit(cfg.ERR_INTEGRATION) print("OK: Custom templates applied successfully!") else: @@ -234,6 +235,9 @@ def modify_lua_build_script(cfg) -> None: 'Plugin.sdk.shared.includedirs', 'Plugin.authoring.includedirs' ] + + if (cfg.wwise_with_test_project): + sections.extend(['Plugin.sdk.test.includedirs']) new_lines = [] inside_section = False @@ -247,30 +251,15 @@ def modify_lua_build_script(cfg) -> None: new_lines.append(line) continue - # If inside a section, look for the line that contains just the closing brace '}' - if inside_section: - if stripped == '}': + # If inside a section, inject immediately after the opening brace '{' + if inside_section and stripped == '{': - # Walk backwards to check if faust path exists - already_added = False - for check_line in reversed(new_lines): - if str(cfg.faust_include_dir) in check_line: - already_added = True - break - if check_line.strip() == '': # empty line - skip - continue - if check_line.strip() == '{': # hit start of block, stop checking - break - - if not already_added: - # Insert with the same indentation as the closing brace - indent = line[:line.index('}')] - insert_line = f'{indent}"{cfg.faust_include_dir.as_posix()}",\n' # convert to posix path before replacing - new_lines.append(insert_line) - - new_lines.append(line) - inside_section = False - continue + new_lines.append(line) + + insert_line = f'\t"{cfg.faust_include_dir.as_posix()}",\n' # convert to posix path before replacing + new_lines.append(insert_line) + inside_section = False + continue # Normal line outside or inside section new_lines.append(line) @@ -282,7 +271,7 @@ def modify_lua_build_script(cfg) -> None: print("OK : Updated Lua build script with Faust include paths") os.chdir(original_dir) -def replace_channel_config_line(cfg) -> bool: +def replace_channel_config_line(cfg) -> None: """ Replaces the entire line that sets the speaker configuration in the scaffolding.{WwiseVersion_Major}\source\SoundEnginePlugin\ProjectNameSource.cpp file with a provided value. @@ -302,7 +291,7 @@ def replace_channel_config_line(cfg) -> bool: lines = filepath.read_text(encoding="utf-8").splitlines(keepends=True) except FileNotFoundError: print(f"Error: File not found: {filepath}") - return False + sys.exit(cfg.ERR_INTEGRATION) for i, line in enumerate(lines): if anchor in line: @@ -315,7 +304,6 @@ def replace_channel_config_line(cfg) -> bool: try: filepath.write_text("".join(lines), encoding="utf-8") - return True except Exception as e: print(f"Error writing file: {e}") - return False + sys.exit(cfg.ERR_INTEGRATION) diff --git a/architecture/wwise/jsonprocessor.py b/architecture/wwise/jsonprocessor.py index bbe1ced8fe..ba4a974589 100644 --- a/architecture/wwise/jsonprocessor.py +++ b/architecture/wwise/jsonprocessor.py @@ -7,7 +7,7 @@ import os import shutil import json -from utils import ensure_valid_plugin_name +from utils import ensure_valid_plugin_name, get_installation_location def process_json_configuration(cfg) -> None : """ @@ -23,6 +23,8 @@ def process_json_configuration(cfg) -> None : - author - description - wwise template directory + - build location + - installation location Args: cfg (Config): The configuration object to update. @@ -70,7 +72,15 @@ def process_json_configuration(cfg) -> None : cfg.plugin_type = "source" cfg.plugin_suffix = "Source" cfg.wwise_plugin_interface = None # reset the plugin_interface to None - + + # Determine plugin interface (in-place or out-of-place) in case of effect plugin + if (cfg.plugin_type == "effect" and cfg.num_inputs!=cfg.num_outputs): + print("[Warning]: Misalignment between amount of input and output requested channels by the Faust program will change the plugin type from in-place to out-of-place.") + print(f"\tWwise FX plugins require the same amount of input/output channels. In this case {cfg.num_inputs} != {cfg.num_outputs}") + if (cfg.wwise_plugin_interface == "in-place"): + cfg.wwise_plugin_interface = "out-of-place" + print("\tDefaulting effect plugin interface from \'in-place\' to \'out-of-place\'.") + #Set the wwise_template_dir, the directory where the wwise template files are stored cfg.wwise_template_dir = os.path.join(cfg.faust_dsp_dir, "wwise", "scaffolding."+cfg.patch_version, cfg.plugin_type) if (cfg.plugin_type == "effect"): @@ -97,7 +107,10 @@ def process_json_configuration(cfg) -> None : if isinstance(item, dict) and 'description' in item: cfg.description = item['description'] break - + + cfg.build_location = os.path.join(cfg.output_dir, cfg.plugin_name) + cfg.install_location = get_installation_location(cfg) + except json.JSONDecodeError as e: print(f"Error {cfg.ERR_JSON_PARSE}: Failed to parse JSON: {e}") sys.exit(cfg.ERR_JSON_PARSE) diff --git a/architecture/wwise/orchestrator.py b/architecture/wwise/orchestrator.py index 05d8f0fa04..36e3d1b263 100644 --- a/architecture/wwise/orchestrator.py +++ b/architecture/wwise/orchestrator.py @@ -22,6 +22,7 @@ Remove temporary files """ +import cmd import os import sys import shutil @@ -87,14 +88,14 @@ def setup_environment(self, args: Optional[List[str]]=None) -> None: if self.patch_version not in self.supportedWwiseVersions: sys.stderr.write(f"Unsupported Wwise version : {self.patch_version}. \ Available Wwise (major) versions: {self.supportedWwiseVersions}") - sys.exit(cfg.ERR_ENVIRONMENT) + sys.exit(self.ERR_ENVIRONMENT) parsed_args = utils.parse_arguments(self.cfg, args) print("------------------------------------------Preliminary Step : setup and validate environment") - # conditionally edit variables across different platforms (windows/macOs) - utils.platform_dependent_setup(self.cfg, parsed_args) + # conditionally edit variables across different operating systems (windows/macOs) + utils.os_dependent_setup(self.cfg, parsed_args) # Wwise-related options utils.create_wwise_config(self.cfg, parsed_args) @@ -153,6 +154,10 @@ def compile_dsp_file(self) -> None: jsonprocessor.process_json_configuration(self.cfg) + self.cfg.plugin_print() # print finalized configuration, after having parsed the faust't output json file + self.cfg.lock() # lock config to deprive any further modifications of its internal state, making it immutable + self.cfg.to_json() # save the config into a file immediately after locking + if (self.wwise_speaker_cfg_channel_mask and \ self.num_outputs!=speaker_config_options[self.wwise_speaker_cfg_channel_mask]): print("Speaker configuration provided does not match with number of outputs supported by the Faust program.") @@ -160,10 +165,6 @@ def compile_dsp_file(self) -> None: print(f"Channel config mask provided : {self.wwise_speaker_cfg_channel_mask} --> {speaker_config_options[self.wwise_speaker_cfg_channel_mask]} num channels") sys.exit(self.ERR_INVALID_INPUT) - self.cfg.plugin_print() # print finalized configuration, after having parsed the faust't output json file - self.cfg.lock() # lock config to deprive any further modifications of its internal state, making it immutable - self.cfg.to_json() # save the config into a file immediately after locking - print("OK : DSP compiling step was completed successfully!") # ========================================================================= @@ -189,6 +190,9 @@ def generate_wwise_project(self) -> None: "--no-prompt" ] + if self.patch_version in ["2025", "2026"]: + cmd.extend(["--with", self.wwise_with_test_project]) + if self.wwise_plugin_interface == "out-of-place": cmd.extend(["--out-of-place"]) @@ -267,10 +271,13 @@ def build_plugin(self) -> None: cmd = [ "python", self.wp_script, "build", + self.wwise_platform, "-c", self.wwise_configuration, - "-x", self.wwise_arch ] + if self.wwise_arch: + cmd.extend(["-x", self.wwise_arch]) + if self.wwise_toolset: cmd.extend(["--toolset", self.wwise_toolset]) @@ -283,8 +290,6 @@ def build_plugin(self) -> None: if self.wwise_toolchain_env_script: cmd.extend(["--toolchain-env-script", self.wwise_toolchain_env_script]) - cmd.extend([self.wwise_platform]) - utils.run_system_command(cmd, self.ERR_BUILD) os.chdir(original_dir) diff --git a/architecture/wwise/parameters.py b/architecture/wwise/parameters.py index 7c9fd3fb8a..07ef9b4180 100644 --- a/architecture/wwise/parameters.py +++ b/architecture/wwise/parameters.py @@ -40,6 +40,7 @@ def __init__(self, data: Dict[str, Any], faustfloat_isDouble : bool): self.io_type = self._derive_io_type() self.initValue = self._derive_init_value(self.init) + self.num_decimals = self._derive_decimals(self.step) self.paramVarname = self.varname self.paramCastedType = self._derive_casted_type(faustfloatType) self.isRTPC = self._derive_is_rtpc() @@ -53,6 +54,7 @@ def __init__(self, data: Dict[str, Any], faustfloat_isDouble : bool): self.Wwise_Type_Specific_GetFunction = self._derive_Wwise_GetFunction() def _derive_io_type(self): + """Determine if the parameter is an input or output based on its type. The only outputs are bargraphs.""" if self.is_bargraph(): return "output" return "input" @@ -73,6 +75,14 @@ def _derive_init_value(self, init_value : Any) -> str: "button": "false" }.get(self.type, "0") + def _derive_decimals(self, step: Any) -> int: + """Derive the number of decimal places from the step value. Max decimals supported in Wwise Authoring part is 3.""" + step_str = f"{step:.10f}".rstrip('0') # avoid scientific notation + if '.' in step_str: + num_decimals = len(step_str.split('.')[1]) + return min(num_decimals, 3) + return 0 + def _derive_casted_type(self, faustfloatType : str) -> str: """Map Faust UI type to C++ type.""" return { @@ -86,9 +96,7 @@ def _derive_casted_type(self, faustfloatType : str) -> str: }.get(self.type, "auto") def _derive_is_rtpc(self) -> str: - """ - Check metadata to see if RTPC is enabled. - """ + """Check metadata to see if RTPC is enabled.""" try: meta = self.raw.get("meta", []) for item in meta: @@ -103,6 +111,7 @@ def _derive_is_rtpc(self) -> str: return "NonRTPC" def _derive_rtpc_type(self, val): + """Derive the RTPC type from the metadata value.""" val = val.lower() return { "additive": "Additive", @@ -184,7 +193,9 @@ def default_value(self) -> str: return self.initValue or "0" def is_bargraph(self) -> bool: + """Return True if this parameter is a bargraph (horizontal or vertical).""" return self.type=="vbargraph" or self.type=="hbargraph" def xml_applicable(self) -> bool: + """Return True if this parameter should be included in the Wwise XML properties.""" return not self.is_bargraph() \ No newline at end of file diff --git a/architecture/wwise/scaffolding.2024/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2024/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp index 937e89b604..e5cd99a7c2 100644 --- a/architecture/wwise/scaffolding.2024/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp +++ b/architecture/wwise/scaffolding.2024/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -27,7 +27,6 @@ the specific language governing permissions and limitations under the License. #include "../${name}Config.h" #include -#include AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) { @@ -61,14 +60,18 @@ AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPlug channelsAvail = in_rFormat.channelConfig.uNumChannels; const int numInputs = m_dsp.getNumInputs(); const int numOutputs = m_dsp.getNumOutputs(); - // Runtime error in case of misalignment between amount of input and output requested channels by the Faust program + + // Note: This condition should never happen here, since the faust2wwise::jsonprocessor changes the plugin_interface to "out-of-place" in such a case. + // Runtime error in case of misalignment between amount of input and output requested channels by the Faust program. if (numInputs != numOutputs){ char errorMsg[256]; snprintf(errorMsg, sizeof(errorMsg), - "[ERROR]: Wwise FX plugins require the same amount of input/output channels. In this case {} != {}", + "[ERROR]: Misalignment between amount of input and output requested channels by the Faust program is unsupported for in-place effect plugins.", + "Now the case of misalignment between amount of input and output requested channels by the Faust is handled by out-of-place effect plugins. In this case, please use an faust2wwise with \'--out-of-place\' argument instead.", + "Wwise in-place FX plugins require the same amount of input/output channels. In this case {} != {}", numInputs, numOutputs); AKPLATFORM::OutputDebugMsg(errorMsg); - throw std::runtime_error(errorMsg); + return AK_NotImplemented; } numChannels = numInputs; diff --git a/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp index 7df0cf188c..5846358522 100644 --- a/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp +++ b/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -29,7 +29,6 @@ the specific language governing permissions and limitations under the License. #include #include -#include AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) { @@ -65,16 +64,6 @@ AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPlug numInputs = m_dsp.getNumInputs(); numOutputs = m_dsp.getNumOutputs(); - // Runtime error in case of misalignment between amount of input and output requested channels by the Faust program - if (numInputs != numOutputs){ - char errorMsg[256]; - snprintf(errorMsg, sizeof(errorMsg), - "[ERROR]: Wwise FX plugins require the same amount of input/output channels. In this case {} != {}", - numInputs, numOutputs); - AKPLATFORM::OutputDebugMsg(errorMsg); - throw std::runtime_error(errorMsg); - } - // resize and initialize the faust io buffers with nullptr faust_inputs.resize(numInputs,nullptr); faust_outputs.resize(numOutputs,nullptr); @@ -170,14 +159,13 @@ void ${name}FX::Execute(AkAudioBuffer* in_pBuffer, AkUInt32 in_ulnOffset, AkAudi } } - // Fill rest of the channels, in case channelsAvail are less then numInputs. + // Fill rest of the channels, in case channelsAvail are less then numInputs/numOutputs. // This condition can be evaluated as true only once. - if (channelsAvail < numInputs) + // Note: now the case of misalignment between amount of input and output requested channels by the Faust is handled by filling the rest of the input channels with silence and allocating memory for the output channels. + if (!faustIOChannelsFilledOnce) { fillRestOfBuffersWithSilence(framesToProcess); - // micro-optimization - numInputs = channelsAvail; - numOutputs = channelsAvail; + faustIOChannelsFilledOnce = true; } m_dsp.compute(static_cast(framesToProcess), faust_inputs.data(), faust_outputs.data()); diff --git a/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h b/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h index 9717b3f817..dc014ffc8e 100644 --- a/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h +++ b/architecture/wwise/scaffolding.2024/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h @@ -73,6 +73,7 @@ class ${name}FX int numInputs {0}, numOutputs {0}, channelsAvail{0}; std::vector faust_inputs; std::vector faust_outputs; + bool faustIOChannelsFilledOnce {false}; }; #endif // ${name}FX_H diff --git a/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp new file mode 100644 index 0000000000..737ca1414b --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -0,0 +1,152 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FX.h" +#include "../${name}Config.h" + +#include + +AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FX()); +} + +AK::IAkPluginParam* Create${name}FXParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}FX, AkPluginTypeEffect, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}FX::${name}FX() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}FX::~${name}FX() +{ +} + +AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}FXParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + channelsAvail = in_rFormat.channelConfig.uNumChannels; + const int numInputs = m_dsp.getNumInputs(); + const int numOutputs = m_dsp.getNumOutputs(); + + // Note: This condition should never happen here, since the faust2wwise::jsonprocessor changes the plugin_interface to "out-of-place" in such a case. + // Runtime error in case of misalignment between amount of input and output requested channels by the Faust program. + if (numInputs != numOutputs){ + char errorMsg[256]; + snprintf(errorMsg, sizeof(errorMsg), + "[ERROR]: Misalignment between amount of input and output requested channels by the Faust program is unsupported for in-place effect plugins.", + "Now the case of misalignment between amount of input and output requested channels by the Faust is handled by out-of-place effect plugins. In this case, please use an faust2wwise with \'--out-of-place\' argument instead.", + "Wwise in-place FX plugins require the same amount of input/output channels. In this case {} != {}", + numInputs, numOutputs); + AKPLATFORM::OutputDebugMsg(errorMsg); + return AK_NotImplemented; + } + numChannels = numInputs; + + // resize and initialize the faust io (in-place) buffer with nullptr + faust_inplace_buffer.resize(numChannels, nullptr); + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + +AKRESULT ${name}FX::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FX::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}FX::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeEffect; + out_rPluginInfo.bIsInPlace = true; + out_rPluginInfo.bCanProcessObjects = false; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}FX::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust channels with silence, + // and only in case the channels requested by the faust dsp program is + // greater than the available channels wwise can support. + + if (faust_inplace_buffer[channelsAvail] == nullptr) + { + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + } + // Fill silent channels + for (int ch = channelsAvail; ch < numChannels; ++ch) { + faust_inplace_buffer[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled the input(/output) channels with silence.\n"); + } +} + +void ${name}FX::Execute(AkAudioBuffer* io_pBuffer) +{ + channelsAvail = static_cast(io_pBuffer->NumChannels()); + const AkUInt32 framesToProcess = io_pBuffer->uValidFrames; + + <${isRTPC}.${RTPCname});>> + + for (int ch = 0; ch < numChannels; ++ch) { + if (ch < channelsAvail ){ + faust_inplace_buffer[ch] = io_pBuffer->GetChannel(ch); + } + } + + if (channelsAvail < numChannels) + { + fillRestOfBuffersWithSilence(framesToProcess); + numChannels = channelsAvail; + } + + m_dsp.compute(static_cast(framesToProcess), faust_inplace_buffer.data(), faust_inplace_buffer.data()); +} + +AKRESULT ${name}FX::TimeSkip(AkUInt32 in_uFrames) +{ + return AK_DataReady; +} diff --git a/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h new file mode 100644 index 0000000000..8810921c37 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h @@ -0,0 +1,76 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FX_H +#define ${name}FX_H + +#include "${name}FXParams.h" +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__effects.html +/// for the documentation about effect plug-ins +class ${name}FX + : public AK::IAkInPlaceEffectPlugin +{ +public: + ${name}FX(); + ~${name}FX(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Effect plug-in DSP execution. + void Execute(AkAudioBuffer* io_pBuffer) override; + + /// Skips execution of some frames, when the voice is virtual playing from elapsed time. + /// This can be used to simulate processing that would have taken place (e.g. update internal state). + /// Return AK_DataReady or AK_NoMoreData, depending if there would be audio output or not at that point. + AKRESULT TimeSkip(AkUInt32 in_uFrames) override; + +private: + ${name}FXParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkEffectPluginContext* m_pContext; + + void fillRestOfBuffersWithSilence(const AkUInt32 ); + std::vector silenceBuffer; + int numChannels {0}, channelsAvail{0}; + std::vector faust_inplace_buffer; +}; + +#endif // ${name}FX_H diff --git a/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp new file mode 100644 index 0000000000..8f28f96c01 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FXParams.h" + +#include + +${name}FXParams::${name}FXParams() +{ +} + +${name}FXParams::~${name}FXParams() +{ +} + +${name}FXParams::${name}FXParams(const ${name}FXParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}FXParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams(*this)); +} + +AKRESULT ${name}FXParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fPlaceholder = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}FXParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FXParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fPlaceholder = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}FXParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_PLACEHOLDER_ID: + RTPC.fPlaceholder = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_PLACEHOLDER_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h new file mode 100644 index 0000000000..10089f63e0 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FXParams_H +#define ${name}FXParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_PLACEHOLDER_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fPlaceholder; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}FXParams + : public AK::IAkPluginParam +{ + ${name}FXParams(); + ${name}FXParams(const ${name}FXParams& in_rParams); + + ~${name}FXParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}FXParams_H diff --git a/architecture/wwise/scaffolding.2025/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2025/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..38e879f294 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}FXFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Placeholder")); + <> + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}FX // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp new file mode 100644 index 0000000000..41a1513bd9 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -0,0 +1,187 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FX.h" +#include "../${name}Config.h" + +#include +#include + +AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FX()); +} + +AK::IAkPluginParam* Create${name}FXParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}FX, AkPluginTypeEffect, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}FX::${name}FX() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}FX::~${name}FX() +{ +} + +AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}FXParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + channelsAvail = in_rFormat.channelConfig.uNumChannels; + + numInputs = m_dsp.getNumInputs(); + numOutputs = m_dsp.getNumOutputs(); + + // resize and initialize the faust io buffers with nullptr + faust_inputs.resize(numInputs,nullptr); + faust_outputs.resize(numOutputs,nullptr); + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + +AKRESULT ${name}FX::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FX::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}FX::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeEffect; + out_rPluginInfo.bIsInPlace = false; + out_rPluginInfo.bCanProcessObjects = false; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}FX::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust input channels with silence + // and allocate memory for the output buffers using the helperOutBuffs vector. + // This is done only in case the channels requested by the faust dsp program + // is greater than the available channels wwise can support. + + if ( faust_inputs[channelsAvail]==nullptr || faust_outputs[channelsAvail]==nullptr) + { + + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + } + + if (faust_inputs[channelsAvail]==nullptr) + { + // Fill silent input channels + for (int ch = channelsAvail; ch < numInputs; ++ch) { + faust_inputs[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled input channels with silence.\n"); + } + + if (faust_outputs[channelsAvail]==nullptr) + { + // allocate storage for the rest of the output buffer channels using the helperOutBuff vector + helperOutBuff.resize(numOutputs - channelsAvail); + for (int ch = channelsAvail; ch < numOutputs; ++ch) { + int idx = ch-channelsAvail; + helperOutBuff[idx].resize(framesToProcess); + faust_outputs[ch] = helperOutBuff[idx].data(); + } + AKPLATFORM::OutputDebugMsg("Set the output buffer with a zeroed array.\n"); + } + } +} + +void ${name}FX::Execute(AkAudioBuffer* in_pBuffer, AkUInt32 in_ulnOffset, AkAudioBuffer* out_pBuffer) +{ + // Technical note: + // This function assumes that the FAUST DSP consumes and produces exactly the same number of frames.(framesProduced variable is discarded) + // The number of channels are as many as the DSP supports and extra ones are ignored + // If the DSP needs a different frame ratio, this logic might not be correct. + + channelsAvail = static_cast(in_pBuffer->NumChannels()); + const AkUInt32 framesToProcess = in_pBuffer->uValidFrames; + + <${isRTPC}.${RTPCname});>> + + for (int ch = 0; ch < numInputs; ++ch) + { + if (ch < channelsAvail) + { + faust_inputs[ch] = in_pBuffer->GetChannel(ch) + in_ulnOffset; + } + } + + for (int ch = 0; ch < numOutputs; ++ch) + { + if (ch < channelsAvail ) + { + faust_outputs[ch] = out_pBuffer->GetChannel(ch) + out_pBuffer->uValidFrames; + } + } + + // Fill rest of the channels, in case channelsAvail are less then numInputs/numOutputs. + // This condition can be evaluated as true only once. + // Note: now the case of misalignment between amount of input and output requested channels by the Faust is handled by filling the rest of the input channels with silence and allocating memory for the output channels. + if (!faustIOChannelsFilledOnce) + { + fillRestOfBuffersWithSilence(framesToProcess); + faustIOChannelsFilledOnce = true; + } + + m_dsp.compute(static_cast(framesToProcess), faust_inputs.data(), faust_outputs.data()); + + in_pBuffer->uValidFrames -= framesToProcess; + out_pBuffer->uValidFrames += framesToProcess; + + if (in_pBuffer->eState == AK_NoMoreData && in_pBuffer->uValidFrames == 0) + out_pBuffer->eState = AK_NoMoreData; + else if (out_pBuffer->uValidFrames == out_pBuffer->MaxFrames()) + out_pBuffer->eState = AK_DataReady; + else + out_pBuffer->eState = AK_DataNeeded; +} + +AKRESULT ${name}FX::TimeSkip(AkUInt32 &io_uFrames) +{ + return AK_DataReady; +} diff --git a/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h new file mode 100644 index 0000000000..92932ce431 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h @@ -0,0 +1,79 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FX_H +#define ${name}FX_H + +#include "${name}FXParams.h" +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__effects.html +/// for the documentation about effect plug-ins +class ${name}FX + : public AK::IAkOutOfPlaceEffectPlugin +{ +public: + ${name}FX(); + ~${name}FX(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Effect plug-in DSP execution. + void Execute(AkAudioBuffer* in_pBuffer, AkUInt32 in_ulnOffset, AkAudioBuffer* out_pBuffer) override; + + /// Skips execution of some frames, when the voice is virtual playing from elapsed time. + /// This can be used to simulate processing that would have taken place (e.g. update internal state). + /// Return AK_DataReady or AK_NoMoreData, depending if there would be audio output or not at that point. + AKRESULT TimeSkip(AkUInt32 &io_uFrames) override; + +private: + ${name}FXParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkEffectPluginContext* m_pContext; + + void fillRestOfBuffersWithSilence(const AkUInt32 ); + std::vector silenceBuffer; + std::vector> helperOutBuff; + int numInputs {0}, numOutputs {0}, channelsAvail{0}; + std::vector faust_inputs; + std::vector faust_outputs; + bool faustIOChannelsFilledOnce {false}; +}; + +#endif // ${name}FX_H diff --git a/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp new file mode 100644 index 0000000000..8f28f96c01 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FXParams.h" + +#include + +${name}FXParams::${name}FXParams() +{ +} + +${name}FXParams::~${name}FXParams() +{ +} + +${name}FXParams::${name}FXParams(const ${name}FXParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}FXParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams(*this)); +} + +AKRESULT ${name}FXParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fPlaceholder = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}FXParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FXParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fPlaceholder = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}FXParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_PLACEHOLDER_ID: + RTPC.fPlaceholder = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_PLACEHOLDER_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h new file mode 100644 index 0000000000..10089f63e0 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FXParams_H +#define ${name}FXParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_PLACEHOLDER_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fPlaceholder; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}FXParams + : public AK::IAkPluginParam +{ + ${name}FXParams(); + ${name}FXParams(const ${name}FXParams& in_rParams); + + ~${name}FXParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}FXParams_H diff --git a/architecture/wwise/scaffolding.2025/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2025/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..38e879f294 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}FXFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Placeholder")); + <> + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}FX // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.cpp b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.cpp new file mode 100644 index 0000000000..568ae125c0 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.cpp @@ -0,0 +1,201 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Source.h" +#include "../${name}Config.h" + +#include + +AK::IAkPlugin* Create${name}Source(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}Source()); +} + +AK::IAkPluginParam* Create${name}SourceParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}SourceParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}Source, AkPluginTypeSource, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}Source::${name}Source() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}Source::~${name}Source() +{ +} + +AkUInt32 ${name}Source::GetSpeakerConfigChannelMask(int dsp_outputs){ + + // provide default configurations based on given faust dsp outputs + + AkUInt32 in_uChannelMask; + switch (dsp_outputs) + { + case 1: + in_uChannelMask = AK_SPEAKER_SETUP_MONO; + break; + case 2: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + case 3: + in_uChannelMask = AK_SPEAKER_SETUP_3STEREO; + break; + case 4: + in_uChannelMask = AK_SPEAKER_SETUP_4; + break; + case 5: + in_uChannelMask = AK_SPEAKER_SETUP_5; + break; + case 6: + in_uChannelMask = AK_SPEAKER_SETUP_6; + break; + case 7: + in_uChannelMask = AK_SPEAKER_SETUP_7; + break; + case 8: + in_uChannelMask = AK_SPEAKER_SETUP_7POINT1; + break; + case 9: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9; + break; + case 10: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9POINT1; + break; + case 11: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_10POINT1; + break; + case 12: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_11POINT1; + break; + case 13: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13_751; + break; + case 14: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + break; + default: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + } + if (dsp_outputs > 14) + { + AKPLATFORM::OutputDebugMsg(" [WARNING] dsp_outputs > 14. This is an unsupported speaker configuration. Falling back to 14 channels (AK_SPEAKER_SETUP_AURO_13POINT1_751).\n"); + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + } + + return in_uChannelMask; +} + +AKRESULT ${name}Source::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}SourceParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + m_durationHandler.Setup(m_pParams->RTPC.fDuration, in_pContext->GetNumLoops(), in_rFormat.uSampleRate); + + numOutputs = m_dsp.getNumOutputs(); + faust_outputs.resize(numOutputs); + + + in_rFormat.channelConfig.SetStandard( GetSpeakerConfigChannelMask(numOutputs) ); + speakersAvail = in_rFormat.channelConfig.uNumChannels; + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + +AKRESULT ${name}Source::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}Source::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}Source::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeSource; + out_rPluginInfo.bIsInPlace = true; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}Source::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust output channels with silence, ... + // ... and only in case the channels requested by the faust dsp program is greater + // than the available channels wwise can support. + + static std::vector silenceBuffer; + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + + } + + // Fill silent channels + if (!faust_outputs[speakersAvail]) + { + for (AkUInt32 ch = speakersAvail; ch < static_cast(numOutputs); ++ch) { + faust_outputs[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled the silence buffer!\n"); + } +} + +void ${name}Source::Execute(AkAudioBuffer* out_pBuffer) +{ + m_durationHandler.SetDuration(m_pParams->RTPC.fDuration); + m_durationHandler.ProduceBuffer(out_pBuffer); + + <${isRTPC}.${RTPCname} );>> + + for (AkUInt32 ch = 0; ch < speakersAvail; ++ch) + { + faust_outputs[ch] = out_pBuffer->GetChannel(ch); + } + + const AkUInt32 framesToProcess = out_pBuffer->uValidFrames; + + fillRestOfBuffersWithSilence(framesToProcess); + + m_dsp.compute(static_cast(framesToProcess), nullptr, faust_outputs.data()); +} + +AkReal32 ${name}Source::GetDuration() const +{ + return m_durationHandler.GetDuration() * 1000.0f; +} diff --git a/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.h b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.h new file mode 100644 index 0000000000..9074927cbe --- /dev/null +++ b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSource.h @@ -0,0 +1,77 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}Source_H +#define ${name}Source_H + +#include "${name}SourceParams.h" + +#include +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__source.html +/// for the documentation about source plug-ins +class ${name}Source + : public AK::IAkSourcePlugin +{ +public: + ${name}Source(); + ~${name}Source(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Source plug-in DSP execution. + void Execute(AkAudioBuffer* io_pBuffer) override; + + /// This method is called to determine the approximate duration (in ms) of the source. + AkReal32 GetDuration() const override; + +private: + ${name}SourceParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkSourcePluginContext* m_pContext; + AkFXDurationHandler m_durationHandler; + + AkUInt32 GetSpeakerConfigChannelMask(int); + void fillRestOfBuffersWithSilence(const AkUInt32); + int numOutputs {0},speakersAvail{0}; + std::vector faust_outputs; +}; + +#endif // ${name}Source_H diff --git a/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.cpp b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.cpp new file mode 100644 index 0000000000..d1b904665c --- /dev/null +++ b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}SourceParams.h" + +#include + +${name}SourceParams::${name}SourceParams() +{ +} + +${name}SourceParams::~${name}SourceParams() +{ +} + +${name}SourceParams::${name}SourceParams(const ${name}SourceParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}SourceParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}SourceParams(*this)); +} + +AKRESULT ${name}SourceParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fDuration = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}SourceParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}SourceParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fDuration = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}SourceParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_DURATION_ID: + RTPC.fDuration = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_DURATION_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.h b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.h new file mode 100644 index 0000000000..dcb6c0b812 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/source/SoundEnginePlugin/ProjectNameSourceParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}SourceParams_H +#define ${name}SourceParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_DURATION_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fDuration; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}SourceParams + : public AK::IAkPluginParam +{ + ${name}SourceParams(); + ${name}SourceParams(const ${name}SourceParams& in_rParams); + + ~${name}SourceParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}SourceParams_H diff --git a/architecture/wwise/scaffolding.2025/source/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2025/source/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..e59c799a85 --- /dev/null +++ b/architecture/wwise/scaffolding.2025/source/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}SourceFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Duration")); + <> + + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}Source // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp new file mode 100644 index 0000000000..93a6c13bc8 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -0,0 +1,152 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FX.h" +#include "../${name}Config.h" + +#include + +AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FX()); +} + +AK::IAkPluginParam* Create${name}FXParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}FX, AkPluginTypeEffect, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}FX::${name}FX() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}FX::~${name}FX() +{ +} + +AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}FXParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + channelsAvail = in_rFormat.channelConfig.uNumChannels; + const int numInputs = m_dsp.getNumInputs(); + const int numOutputs = m_dsp.getNumOutputs(); + + // Note: This condition should never happen here, since the faust2wwise::jsonprocessor changes the plugin_interface to "out-of-place" in such a case. + // Runtime error in case of misalignment between amount of input and output requested channels by the Faust program. + if (numInputs != numOutputs){ + char errorMsg[256]; + snprintf(errorMsg, sizeof(errorMsg), + "[ERROR]: Misalignment between amount of input and output requested channels by the Faust program is unsupported for in-place effect plugins.", + "Now the case of misalignment between amount of input and output requested channels by the Faust is handled by out-of-place effect plugins. In this case, please use an faust2wwise with \'--out-of-place\' argument instead.", + "Wwise in-place FX plugins require the same amount of input/output channels. In this case {} != {}", + numInputs, numOutputs); + AKPLATFORM::OutputDebugMsg(errorMsg); + return AK_NotImplemented; + } + numChannels = numInputs; + + // resize and initialize the faust io (in-place) buffer with nullptr + faust_inplace_buffer.resize(numChannels, nullptr); + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + +AKRESULT ${name}FX::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FX::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}FX::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeEffect; + out_rPluginInfo.bIsInPlace = true; + out_rPluginInfo.bCanProcessObjects = false; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}FX::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust channels with silence, + // and only in case the channels requested by the faust dsp program is + // greater than the available channels wwise can support. + + if (faust_inplace_buffer[channelsAvail] == nullptr) + { + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + } + // Fill silent channels + for (int ch = channelsAvail; ch < numChannels; ++ch) { + faust_inplace_buffer[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled the input(/output) channels with silence.\n"); + } +} + +void ${name}FX::Execute(AkAudioBuffer* io_pBuffer) +{ + channelsAvail = static_cast(io_pBuffer->NumChannels()); + const AkUInt32 framesToProcess = io_pBuffer->uValidFrames; + + <${isRTPC}.${RTPCname});>> + + for (int ch = 0; ch < numChannels; ++ch) { + if (ch < channelsAvail ){ + faust_inplace_buffer[ch] = io_pBuffer->GetChannel(ch); + } + } + + if (channelsAvail < numChannels) + { + fillRestOfBuffersWithSilence(framesToProcess); + numChannels = channelsAvail; + } + + m_dsp.compute(static_cast(framesToProcess), faust_inplace_buffer.data(), faust_inplace_buffer.data()); +} + +AKRESULT ${name}FX::TimeSkip(AkUInt32 in_uFrames) +{ + return AK_DataReady; +} diff --git a/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h new file mode 100644 index 0000000000..8810921c37 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFX.h @@ -0,0 +1,76 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FX_H +#define ${name}FX_H + +#include "${name}FXParams.h" +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__effects.html +/// for the documentation about effect plug-ins +class ${name}FX + : public AK::IAkInPlaceEffectPlugin +{ +public: + ${name}FX(); + ~${name}FX(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Effect plug-in DSP execution. + void Execute(AkAudioBuffer* io_pBuffer) override; + + /// Skips execution of some frames, when the voice is virtual playing from elapsed time. + /// This can be used to simulate processing that would have taken place (e.g. update internal state). + /// Return AK_DataReady or AK_NoMoreData, depending if there would be audio output or not at that point. + AKRESULT TimeSkip(AkUInt32 in_uFrames) override; + +private: + ${name}FXParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkEffectPluginContext* m_pContext; + + void fillRestOfBuffersWithSilence(const AkUInt32 ); + std::vector silenceBuffer; + int numChannels {0}, channelsAvail{0}; + std::vector faust_inplace_buffer; +}; + +#endif // ${name}FX_H diff --git a/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp new file mode 100644 index 0000000000..8f28f96c01 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FXParams.h" + +#include + +${name}FXParams::${name}FXParams() +{ +} + +${name}FXParams::~${name}FXParams() +{ +} + +${name}FXParams::${name}FXParams(const ${name}FXParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}FXParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams(*this)); +} + +AKRESULT ${name}FXParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fPlaceholder = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}FXParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FXParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fPlaceholder = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}FXParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_PLACEHOLDER_ID: + RTPC.fPlaceholder = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_PLACEHOLDER_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h new file mode 100644 index 0000000000..10089f63e0 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (in-place)/SoundEnginePlugin/ProjectNameFXParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FXParams_H +#define ${name}FXParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_PLACEHOLDER_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fPlaceholder; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}FXParams + : public AK::IAkPluginParam +{ + ${name}FXParams(); + ${name}FXParams(const ${name}FXParams& in_rParams); + + ~${name}FXParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}FXParams_H diff --git a/architecture/wwise/scaffolding.2026/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2026/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..38e879f294 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (in-place)/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}FXFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Placeholder")); + <> + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}FX // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp new file mode 100644 index 0000000000..9a7188923f --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.cpp @@ -0,0 +1,187 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FX.h" +#include "../${name}Config.h" + +#include + +AK::IAkPlugin* Create${name}FX(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FX()); +} + +AK::IAkPluginParam* Create${name}FXParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}FX, AkPluginTypeEffect, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}FX::${name}FX() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}FX::~${name}FX() +{ +} + +AKRESULT ${name}FX::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}FXParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + channelsAvail = in_rFormat.channelConfig.uNumChannels; + + numInputs = m_dsp.getNumInputs(); + numOutputs = m_dsp.getNumOutputs(); + + // resize and initialize the faust io buffers with nullptr + faust_inputs.resize(numInputs,nullptr); + faust_outputs.resize(numOutputs,nullptr); + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + + +AKRESULT ${name}FX::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FX::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}FX::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeEffect; + out_rPluginInfo.bIsInPlace = false; + out_rPluginInfo.bCanProcessObjects = false; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}FX::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust input channels with silence + // and allocate memory for the output buffers using the helperOutBuffs vector. + // This is done only in case the channels requested by the faust dsp program + // is greater than the available channels wwise can support. + + if ( faust_inputs[channelsAvail]==nullptr || faust_outputs[channelsAvail]==nullptr) + { + + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + } + + if (faust_inputs[channelsAvail]==nullptr) + { + // Fill silent input channels + for (int ch = channelsAvail; ch < numInputs; ++ch) { + faust_inputs[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled input channels with silence.\n"); + } + + if (faust_outputs[channelsAvail]==nullptr) + { + // allocate storage for the rest of the output buffer channels using the helperOutBuff vector + helperOutBuff.resize(numOutputs - channelsAvail); + for (int ch = channelsAvail; ch < numOutputs; ++ch) { + int idx = ch-channelsAvail; + helperOutBuff[idx].resize(framesToProcess); + faust_outputs[ch] = helperOutBuff[idx].data(); + } + AKPLATFORM::OutputDebugMsg("Set the output buffer with a zeroed array.\n"); + } + } +} + +void ${name}FX::Execute(AkAudioBuffer* in_pBuffer, AkUInt32 in_ulnOffset, AkAudioBuffer* out_pBuffer) +{ + // Technical note: + // This function assumes that the FAUST DSP consumes and produces exactly the same number of frames.(framesProduced variable is discarded) + // The number of channels are as many as the DSP supports and extra ones are ignored + // If the DSP needs a different frame ratio, this logic might not be correct. + + channelsAvail = static_cast(in_pBuffer->NumChannels()); + const AkUInt32 framesToProcess = in_pBuffer->uValidFrames; + + <${isRTPC}.${RTPCname});>> + + for (int ch = 0; ch < numInputs; ++ch) + { + if (ch < channelsAvail) + { + faust_inputs[ch] = in_pBuffer->GetChannel(ch) + in_ulnOffset; + } + } + + for (int ch = 0; ch < numOutputs; ++ch) + { + if (ch < channelsAvail ) + { + faust_outputs[ch] = out_pBuffer->GetChannel(ch) + out_pBuffer->uValidFrames; + } + } + + // Fill rest of the channels, in case channelsAvail are less then numInputs/numOutputs. + // This condition can be evaluated as true only once. + // Note: now the case of misalignment between amount of input and output requested channels by the Faust is handled by filling the rest of the input channels with silence and allocating memory for the output channels. + if (!faustIOChannelsFilledOnce) + { + fillRestOfBuffersWithSilence(framesToProcess); + faustIOChannelsFilledOnce = true; + } + + m_dsp.compute(static_cast(framesToProcess), faust_inputs.data(), faust_outputs.data()); + + in_pBuffer->uValidFrames -= framesToProcess; + out_pBuffer->uValidFrames += framesToProcess; + + if (in_pBuffer->eState == AK_NoMoreData && in_pBuffer->uValidFrames == 0) + out_pBuffer->eState = AK_NoMoreData; + else if (out_pBuffer->uValidFrames == out_pBuffer->MaxFrames()) + out_pBuffer->eState = AK_DataReady; + else + out_pBuffer->eState = AK_DataNeeded; +} + +AKRESULT ${name}FX::TimeSkip(AkUInt32 &io_uFrames) +{ + return AK_DataReady; +} diff --git a/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h new file mode 100644 index 0000000000..92932ce431 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFX.h @@ -0,0 +1,79 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FX_H +#define ${name}FX_H + +#include "${name}FXParams.h" +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__effects.html +/// for the documentation about effect plug-ins +class ${name}FX + : public AK::IAkOutOfPlaceEffectPlugin +{ +public: + ${name}FX(); + ~${name}FX(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkEffectPluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Effect plug-in DSP execution. + void Execute(AkAudioBuffer* in_pBuffer, AkUInt32 in_ulnOffset, AkAudioBuffer* out_pBuffer) override; + + /// Skips execution of some frames, when the voice is virtual playing from elapsed time. + /// This can be used to simulate processing that would have taken place (e.g. update internal state). + /// Return AK_DataReady or AK_NoMoreData, depending if there would be audio output or not at that point. + AKRESULT TimeSkip(AkUInt32 &io_uFrames) override; + +private: + ${name}FXParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkEffectPluginContext* m_pContext; + + void fillRestOfBuffersWithSilence(const AkUInt32 ); + std::vector silenceBuffer; + std::vector> helperOutBuff; + int numInputs {0}, numOutputs {0}, channelsAvail{0}; + std::vector faust_inputs; + std::vector faust_outputs; + bool faustIOChannelsFilledOnce {false}; +}; + +#endif // ${name}FX_H diff --git a/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp new file mode 100644 index 0000000000..8f28f96c01 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}FXParams.h" + +#include + +${name}FXParams::${name}FXParams() +{ +} + +${name}FXParams::~${name}FXParams() +{ +} + +${name}FXParams::${name}FXParams(const ${name}FXParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}FXParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}FXParams(*this)); +} + +AKRESULT ${name}FXParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fPlaceholder = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}FXParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}FXParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fPlaceholder = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}FXParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_PLACEHOLDER_ID: + RTPC.fPlaceholder = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_PLACEHOLDER_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h new file mode 100644 index 0000000000..10089f63e0 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (out-of-place)/SoundEnginePlugin/ProjectNameFXParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}FXParams_H +#define ${name}FXParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_PLACEHOLDER_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fPlaceholder; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}FXParams + : public AK::IAkPluginParam +{ + ${name}FXParams(); + ${name}FXParams(const ${name}FXParams& in_rParams); + + ~${name}FXParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}FXParams_H diff --git a/architecture/wwise/scaffolding.2026/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2026/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..38e879f294 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/effect (out-of-place)/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}FXFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Placeholder")); + <> + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}FX // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.cpp b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.cpp new file mode 100644 index 0000000000..186cd48668 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.cpp @@ -0,0 +1,202 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Source.h" +#include "../${name}Config.h" + +#include + +AK::IAkPlugin* Create${name}Source(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}Source()); +} + +AK::IAkPluginParam* Create${name}SourceParams(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}SourceParams()); +} + +AK_IMPLEMENT_PLUGIN_FACTORY(${name}Source, AkPluginTypeSource, ${name}Config::CompanyID, ${name}Config::PluginID) + +${name}Source::${name}Source() + : m_pParams(nullptr) + , m_pAllocator(nullptr) + , m_pContext(nullptr) +{ +} + +${name}Source::~${name}Source() +{ +} + +AkUInt32 ${name}Source::GetSpeakerConfigChannelMask(int dsp_outputs){ + + // provide default configurations based on given faust dsp outputs + + AkUInt32 in_uChannelMask; + switch (dsp_outputs) + { + case 1: + in_uChannelMask = AK_SPEAKER_SETUP_MONO; + break; + case 2: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + case 3: + in_uChannelMask = AK_SPEAKER_SETUP_3STEREO; + break; + case 4: + in_uChannelMask = AK_SPEAKER_SETUP_4; + break; + case 5: + in_uChannelMask = AK_SPEAKER_SETUP_5; + break; + case 6: + in_uChannelMask = AK_SPEAKER_SETUP_6; + break; + case 7: + in_uChannelMask = AK_SPEAKER_SETUP_7; + break; + case 8: + in_uChannelMask = AK_SPEAKER_SETUP_7POINT1; + break; + case 9: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9; + break; + case 10: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_9POINT1; + break; + case 11: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_10POINT1; + break; + case 12: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_11POINT1; + break; + case 13: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13_751; + break; + case 14: + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + break; + default: + in_uChannelMask = AK_SPEAKER_SETUP_STEREO; + break; + } + if (dsp_outputs > 14) + { + AKPLATFORM::OutputDebugMsg(" [WARNING] dsp_outputs > 14. This is an unsupported speaker configuration. Falling back to 14 channels (AK_SPEAKER_SETUP_AURO_13POINT1_751).\n"); + in_uChannelMask = AK_SPEAKER_SETUP_AURO_13POINT1_751; + } + + return in_uChannelMask; +} + +AKRESULT ${name}Source::Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) +{ + m_pParams = (${name}SourceParams*)in_pParams; + m_pAllocator = in_pAllocator; + m_pContext = in_pContext; + + m_durationHandler.Setup(m_pParams->RTPC.fDuration, in_pContext->GetNumLoops(), in_rFormat.uSampleRate); + + numOutputs = m_dsp.getNumOutputs(); + faust_outputs.resize(numOutputs); + + + in_rFormat.channelConfig.SetStandard( GetSpeakerConfigChannelMask(numOutputs) ); + speakersAvail = in_rFormat.channelConfig.uNumChannels; + + initDSP(static_cast(in_rFormat.uSampleRate)); + + return AK_Success; +} + +AKRESULT ${name}Source::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}Source::Reset() +{ + return AK_Success; +} + +AKRESULT ${name}Source::GetPluginInfo(AkPluginInfo& out_rPluginInfo) +{ + out_rPluginInfo.eType = AkPluginTypeSource; + out_rPluginInfo.bIsInPlace = true; + out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; + return AK_Success; +} + +void ${name}Source::fillRestOfBuffersWithSilence(const AkUInt32 framesToProcess ) +{ + + // Runs only once filling the rest of the faust output channels with silence, ... + // ... and only in case the channels requested by the faust dsp program is greater + // than the available channels wwise can support. + + static std::vector silenceBuffer; + if (silenceBuffer.size() < framesToProcess) { + silenceBuffer.resize(framesToProcess, 0.0f); + + } + + // Fill silent channels + if (!faust_outputs[speakersAvail]) + { + for (AkUInt32 ch = speakersAvail; ch < static_cast(numOutputs); ++ch) { + faust_outputs[ch] = silenceBuffer.data(); + } + AKPLATFORM::OutputDebugMsg("Filled the silence buffer!\n"); + } +} + +void ${name}Source::Execute(AkAudioBuffer* out_pBuffer) +{ + m_durationHandler.SetDuration(m_pParams->RTPC.fDuration); + m_durationHandler.ProduceBuffer(out_pBuffer); + + <${isRTPC}.${RTPCname} );>> + + for (AkUInt32 ch = 0; ch < speakersAvail; ++ch) + { + faust_outputs[ch] = out_pBuffer->GetChannel(ch); + } + + const AkUInt32 framesToProcess = out_pBuffer->uValidFrames; + + fillRestOfBuffersWithSilence(framesToProcess); + + m_dsp.compute(static_cast(framesToProcess), nullptr, faust_outputs.data()); +} + + +AkReal32 ${name}Source::GetDuration() const +{ + return m_durationHandler.GetDuration() * 1000.0f; +} diff --git a/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.h b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.h new file mode 100644 index 0000000000..7802c0b74e --- /dev/null +++ b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSource.h @@ -0,0 +1,77 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}Source_H +#define ${name}Source_H + +#include "${name}SourceParams.h" + +#include +#include "faustdsp.cpp" + +/// See https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__plugins__source.html +/// for the documentation about source plug-ins +class ${name}Source + : public AK::IAkSourcePlugin +{ +public: + ${name}Source(); + ~${name}Source(); + + /// Plug-in initialization. + /// Prepares the plug-in for data processing, allocates memory and sets up the initial conditions. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, AK::IAkSourcePluginContext* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; + + /// Release the resources upon termination of the plug-in. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// The reset action should perform any actions required to reinitialize the + /// state of the plug-in to its original state (e.g. after Init() or on effect bypass). + AKRESULT Reset() override; + + /// Plug-in information query mechanism used when the sound engine requires + /// information about the plug-in to determine its behavior. + AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; + + /// Source plug-in DSP execution. + void Execute(AkAudioBuffer* out_pBuffer) override; + + /// This method is called to determine the approximate duration (in ms) of the source. + AkReal32 GetDuration() const override; + +private: + ${name}SourceParams* m_pParams; + AK::IAkPluginMemAlloc* m_pAllocator; + AK::IAkSourcePluginContext* m_pContext; + AkFXDurationHandler m_durationHandler; + + AkUInt32 GetSpeakerConfigChannelMask(int); + void fillRestOfBuffersWithSilence(const AkUInt32); + int numOutputs {0},speakersAvail{0}; + std::vector faust_outputs; +}; + +#endif // ${name}Source_H diff --git a/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.cpp b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.cpp new file mode 100644 index 0000000000..d1b904665c --- /dev/null +++ b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}SourceParams.h" + +#include + +${name}SourceParams::${name}SourceParams() +{ +} + +${name}SourceParams::~${name}SourceParams() +{ +} + +${name}SourceParams::${name}SourceParams(const ${name}SourceParams& in_rParams) +{ + RTPC = in_rParams.RTPC; + NonRTPC = in_rParams.NonRTPC; + m_paramChangeHandler.SetAllParamChanges(); +} + +AK::IAkPluginParam* ${name}SourceParams::Clone(AK::IAkPluginMemAlloc* in_pAllocator) +{ + return AK_PLUGIN_NEW(in_pAllocator, ${name}SourceParams(*this)); +} + +AKRESULT ${name}SourceParams::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + if (in_ulBlockSize == 0) + { + // Initialize default parameters here + RTPC.fDuration = 0.0f; + <> + m_paramChangeHandler.SetAllParamChanges(); + return AK_Success; + } + + return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); +} + +AKRESULT ${name}SourceParams::Term(AK::IAkPluginMemAlloc* in_pAllocator) +{ + AK_PLUGIN_DELETE(in_pAllocator, this); + return AK_Success; +} + +AKRESULT ${name}SourceParams::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) +{ + AKRESULT eResult = AK_Success; + AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; + + // Read bank data here + RTPC.fDuration = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); + <> + CHECKBANKDATASIZE(in_ulBlockSize, eResult); + m_paramChangeHandler.SetAllParamChanges(); + + return eResult; +} + +AKRESULT ${name}SourceParams::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) +{ + AKRESULT eResult = AK_Success; + + // Handle parameter change here + switch (in_paramID) + { + case PARAM_DURATION_ID: + RTPC.fDuration = *((AkReal32*)in_pValue); + m_paramChangeHandler.SetParamChange(PARAM_DURATION_ID); + break; + <> + default: + eResult = AK_InvalidParameter; + break; + } + + return eResult; +} diff --git a/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.h b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.h new file mode 100644 index 0000000000..dcb6c0b812 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/source/SoundEnginePlugin/ProjectNameSourceParams.h @@ -0,0 +1,82 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#ifndef ${name}SourceParams_H +#define ${name}SourceParams_H + +#include +#include + +// Add parameters IDs here, those IDs should map to the AudioEnginePropertyID +// attributes in the xml property definition. +static const AkPluginParamID PARAM_DURATION_ID = 0; +<> +static const AkUInt32 NUM_PARAMS = 1 +<> +; + +struct ${name}RTPCParams +{ + AkReal32 fDuration; + <> +}; + +struct ${name}NonRTPCParams +{ + <> +}; + +struct ${name}SourceParams + : public AK::IAkPluginParam +{ + ${name}SourceParams(); + ${name}SourceParams(const ${name}SourceParams& in_rParams); + + ~${name}SourceParams(); + + /// Create a duplicate of the parameter node instance in its current state. + IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Initialize the plug-in parameter node interface. + /// Initializes the internal parameter structure to default values or with the provided parameter block if it is valid. + AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Called by the sound engine when a parameter node is terminated. + AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; + + /// Set all plug-in parameters at once using a parameter block. + AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; + + /// Update a single parameter at a time and perform the necessary actions on the parameter changes. + AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; + + AK::AkFXParameterChangeHandler m_paramChangeHandler; + + ${name}RTPCParams RTPC; + ${name}NonRTPCParams NonRTPC; +}; + +#endif // ${name}SourceParams_H diff --git a/architecture/wwise/scaffolding.2026/source/WwisePlugin/ProjectNamePlugin.cpp b/architecture/wwise/scaffolding.2026/source/WwisePlugin/ProjectNamePlugin.cpp new file mode 100644 index 0000000000..7bd5e12801 --- /dev/null +++ b/architecture/wwise/scaffolding.2026/source/WwisePlugin/ProjectNamePlugin.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* +The content of this file includes portions of the AUDIOKINETIC Wwise Technology +released in source code form as part of the SDK installer package. + +Commercial License Usage + +Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology +may use this file in accordance with the end user license agreement provided +with the software or, alternatively, in accordance with the terms contained in a +written agreement between you and Audiokinetic Inc. + +Apache License Usage + +Alternatively, this file may be used under the Apache License, Version 2.0 (the +"Apache License"); you may not use this file except in compliance with the +Apache License. You may obtain a copy of the Apache License at +http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed +under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for +the specific language governing permissions and limitations under the License. + + Copyright (c) 2026 Audiokinetic Inc. +*******************************************************************************/ + +#include "${name}Plugin.h" +#include "../SoundEnginePlugin/${name}SourceFactory.h" + +${name}Plugin::${name}Plugin() +{ +} + +${name}Plugin::~${name}Plugin() +{ +} + +bool ${name}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const +{ + // Write bank data here + in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "Duration")); + <> + return true; +} + +AK_DEFINE_PLUGIN_CONTAINER(${name}); // Create a PluginContainer structure that contains the info for our plugin +AK_EXPORT_PLUGIN_CONTAINER(${name}); // This is a DLL, we want to have a standardized name +AK_ADD_PLUGIN_CLASS_TO_CONTAINER( // Add our CLI class to the PluginContainer + ${name}, // Name of the plug-in container for this shared library + ${name}Plugin, // Authoring plug-in class to add to the plug-in container + ${name}Source // Corresponding Sound Engine plug-in class +); +DEFINE_PLUGIN_REGISTER_HOOK + +DEFINE_PLUGIN_ASSERT_HOOK; // Placeholder assert hook for Wwise plug-ins using AKASSERT (cassert used by default) diff --git a/architecture/wwise/test.py b/architecture/wwise/test.py index 9b5f1f34c0..4721e99fa7 100644 --- a/architecture/wwise/test.py +++ b/architecture/wwise/test.py @@ -68,7 +68,7 @@ def __init__(self, wwiseroot:Path) -> None: def platform_dependent_setup(self) -> None: """ - Function that will eventually be used for platform depended setup. + Function that will eventually be used for host platform depended setup. """ mySystem = platform.system() diff --git a/architecture/wwise/utils.py b/architecture/wwise/utils.py index 0047be991f..06860c0073 100644 --- a/architecture/wwise/utils.py +++ b/architecture/wwise/utils.py @@ -24,21 +24,29 @@ def print_usage() -> None: """ Prints general usage information for the faust2wwise command-line tool. """ - print("Usage:") - print("faust2wwise [options] file.dsp") print("Converts Faust DSP files to Wwise plugins") + print("Usage:") + print("faust2wwise file.dsp [options] [wwise options]") print("") - print("Platform: Windows/macOS/Linux with Wwise SDK") + print("Host-Platforms: Windows/MSYS2/macOS with Wwise SDK") + print("Target-Platforms: Android, Authoring_Windows, Authoring, Windows_vc160, Windows_vc170, WinGC, Mac") print("") print("Requirements: Wwise SDK, Faust compiler, Python") print("") + print("Subcommands (mutually exclusive):") + print(" faust2wwise test [test options] : Run faust2wwise on all .dsp files in a directory for testing purposes") + print(" faust2wwise install-interpreter [install-interpreter options] : Install the Faust interpreter as a Wwise plugin.") + print("") print("Options:") - print(" -h, --help Show this help message") - print(" -o Output directory (default: current directory)") print("") - print("Example:") + print(" -h, --help Show this help message") + print(" -wh,--wwise-help Show Wwise-specific help message") + print(" -o Output directory (default: current directory)") + print(" Type `faust --help` to see all available faust options.") + print("") + print(" Examples:") print(" faust2wwise sine.dsp") - + def print_wwise_help() -> None: """ Prints Wwise-specific command-line options and examples. @@ -47,18 +55,20 @@ def print_wwise_help() -> None: print("") print("Wwise Plugin Options:") print("") - print("Common options for both Premake and Build:") - print(" --platform platform to premake (Authoring_Windows, Authoring, Windows_vc160, Windows_vc170, WinGC)") + print(" Common options for both Premake and Build:") + print(" --platform platform to premake (Android, Authoring_Windows, Authoring, Windows_vc160, Windows_vc170, WinGC, Mac)") print(" --in-place Use in-place processing (default). Uses the same audio buffer for input and output; suitable for most effects without data flow changes") print(" --out-of-place Use out-of-place processing. Requires separate input and output buffers; needed for effects like time-stretching that alter data flow") - print(" --wwise-help show this help message and exit") print("") - print("Premake:") + print(" New:") + print(" --with-test-project configure with test-project : a preconfigured unit test project (Wwise 2025 and 2026 only)") + print("") + print(" Premake:") print(" --toolset toolset used to build on Windows platforms (vc160, vc170).") print(" --debugger Enable lua debugger for premake scripts") print(" --disable-codesign Disable codesign post-build steps") print("") - print("Build:") + print(" Build:") print(" --configuration configuration to build (Debug, Release, Profile,...).") print(" --arch architecture to build (x32, x64, ...).") print(" --build-hooks-file path to a Python file defining one or more of the supported hooks (postbuild) to be called at various step during the build process") @@ -66,8 +76,10 @@ def print_wwise_help() -> None: print(" --toolchain-env-script Path to a \'GetToolchainEnv\' script, which, when executed with a version provided by the toolchain-vers file, returns a comma separated list of environment variables to apply for build step.") print(" --spkcfg Specify an explicit speaker configuration using one of the standard channel mask macros defined in AkSpeakerConfig.h") print("") - print("Example:") + print(" Examples:") print(" faust2wwise myfaustfile.dsp -double -o myWwisePlugin --platform Authoring_Windows --toolset vc170 --configuration Release --arch x64") + print(" faust2wwise myfaustfilter.dsp --out-of-place --configuration Release") + print(" faust2wwise myfaustGenerator.dsp --spkcfg AK_SPEAKER_SETUP_5POINT1") print("") def detect_arch(cfg) -> str: @@ -92,23 +104,54 @@ def detect_arch(cfg) -> str: else: sys.stderr.write( f"[Error] Unknown or unsupported architecture: '{arch}'.\n" - "Please verify if Wwise supports this platform and if yes, update the detect_arch() function to handle this platform .\n" + "Please verify if Wwise supports this architecture and if yes, update the detect_arch() function to handle this target architecture.\n" ) sys.exit(cfg.ERR_ENVIRONMENT) -def platform_dependent_setup(cfg, parsed_args:argparse.Namespace) -> None: +def check_cross_compilation_enabled(cfg, parsed_args:argparse.Namespace, cursys: str) -> bool: + """ + Checks if cross compilation is enabled based on the explicit selection of target platform in the command line arguments. + Cross compilation is enabled if either of the following conditions are met: + 1) If the explicitly selected platform is among the supported cross-compilation platforms. + 2) If the user has explicitly specified a target platform that is different from the current system host platform (i.e. compile for Mac on Windows). + + Args: + cfg (Config): The configuration object to modify. + parsed_args (argparse.Namespace): Parsed arguments from argparse. + cursys (str): The current host platform as returned by platform.system(). + + Returns: + bool: True if cross compilation is enabled, False otherwise. + """ + + if parsed_args.platform: + + if parsed_args.platform in cfg.crossCompilationSupportedPlatforms: + cfg.crossCompilationEnabled = True + return True + + if cursys == "Windows" and parsed_args.platform == "Mac": + cfg.crossCompilationEnabled = True + return True + + # .. can t compile for Windows on an Apple machine. + + return False + +def os_dependent_setup(cfg, parsed_args:argparse.Namespace) -> None: """ - Applies platform-specific configuration to the given config object. - Sets the default Wwise platform and toolset based on the current operating system + Checks if cross compilation is selected. In not, then: + Applies os-specific configuration to the given config object. + Sets the default Wwise target platform and toolset based on the current operating system (host platform) and the parsed command-line arguments. - On Windows: - Uses the specified toolset if provided. - - Otherwise, selects a default based on the Wwise platform. + - Otherwise, selects a default based on the Wwise target platform. - Sets the default Wwise platform to "Authoring". - On macOS: - Disables toolset usage. - - Sets the default Wwise platform to "Mac". + - Sets the default Wwise target platform to "Mac". Args: cfg (Config): The configuration object to modify. @@ -120,6 +163,10 @@ def platform_dependent_setup(cfg, parsed_args:argparse.Namespace) -> None: # Premake-specific options - toolset cursys = platform.system() + + if (check_cross_compilation_enabled(cfg, parsed_args, cursys)): + return + if parsed_args.toolset: if cursys != "Windows": raise ValueError (f"{cursys} detected. Wwise does not support toolset options for this platform. This option is only for windows environments.") @@ -131,7 +178,7 @@ def platform_dependent_setup(cfg, parsed_args:argparse.Namespace) -> None: cfg.wwise_toolset = "vc170" print(f"[WARNING] Using default toolset '{cfg.wwise_toolset}' — it would be better to override it with --toolset command line option.") - # set default platform + # set default target platform if cursys == "Darwin": cfg.wwise_platform = "Mac" # default platform for MacOs elif cursys == "Windows": @@ -147,7 +194,7 @@ def create_wwise_config(cfg, parsed_args:argparse.Namespace) -> None: parsed_args (argparse.Namespace): Parsed arguments from argparse. """ - # Overwrite any platform specific defaults in case explicit platform is passed as an argument + # Overwrite any target platform specific defaults in case explicit platform is passed as an argument if parsed_args.platform: cfg.wwise_platform = parsed_args.platform @@ -162,9 +209,15 @@ def create_wwise_config(cfg, parsed_args:argparse.Namespace) -> None: if parsed_args.arch: cfg.wwise_arch = parsed_args.arch - else: + elif not cfg.crossCompilationEnabled: cfg.wwise_arch = detect_arch(cfg) + if parsed_args.with_test_project: + if (cfg.patch_version not in ["2025", "2026"]): + print(f"WARNING: --with option is only supported for Wwise 2025 and above. Ignoring it.\n") + else: + cfg.wwise_with_test_project = "test-project" + if parsed_args.build_hooks_file: cfg.wwise_build_hooks_file = parsed_args.build_hooks_file @@ -196,15 +249,17 @@ def parse_arguments(cfg, args:Optional[argparse.Namespace] = None) -> argparse.N parser.add_argument('-h', '--help', action='store_true', help='Show help message') parser.add_argument('-o', '--output_dir', help='Output directory') parser.add_argument('dsp_file', nargs='?', help='DSP file to convert') - parser.add_argument('faust_options', nargs='*', help='Additional Faust options') - + parser.add_argument('faust_options', nargs='*', help='Additional Faust options') # Wwise options - parser.add_argument('--platform', help='Target platform for Wwise plugin (Authoring_Windows, Authoring, Windows_vc160, Windows_vc170, WinGC)') + parser.add_argument('-wh', '--wwise-help', action='store_true', help='Show help message for wwise options') + parser.add_argument('--platform', help='Target platform for Wwise plugin (Android, Authoring_Windows, Authoring, Windows_vc160, Windows_vc170, WinGC)') # mutually exclussive in-place and out-of-place effect plugin options. in-place is the default choice. plugin_interface_group = parser.add_mutually_exclusive_group() plugin_interface_group.add_argument('--in-place', dest='plugin_interface', action='store_const', const='in-place', help='Uses the same audio buffer for input and output; suitable for most effects without data flow changes.') plugin_interface_group.add_argument('--out-of-place', dest='plugin_interface', action='store_const', const='out-of-place', help='Use out-of-place processing. Requires separate input and output buffers; needed for effects like time-stretching that alter data flow.') parser.set_defaults(plugin_interface='in-place') + # wwise new options + parser.add_argument('--with-test-project', action='store_true', help='test-project : a preconfigured unit test project.') # wwise premake options parser.add_argument('--toolset', help='toolset used to build on Windows platforms (vc160, vc170).') parser.add_argument('--debugger', action='store_true', help='Enable lua debugger for premake scripts') @@ -226,6 +281,9 @@ def parse_arguments(cfg, args:Optional[argparse.Namespace] = None) -> argparse.N print_usage() print_wwise_help() sys.exit(cfg.SUCCESS_EXIT_CODE) + elif parsed_args.wwise_help: + print_wwise_help() + sys.exit(cfg.SUCCESS_EXIT_CODE) if parsed_args.output_dir: cfg.output_dir = parsed_args.output_dir @@ -281,7 +339,7 @@ def check_wwise_required_arguments(cfg) -> List[str]: missing.append("platform (--platform)") if not cfg.wwise_configuration: missing.append("configuration (--configuration)") - if not cfg.wwise_arch: + if not cfg.wwise_arch and cfg.wwise_platform not in cfg.crossCompilationSupportedPlatforms: missing.append("arch (--arch)") windows_platforms = {"Authoring_Windows", "Windows_vc160", "Windows_vc170", "WinGC"} @@ -295,9 +353,9 @@ def wwise_platform_and_toolset_compatible(cfg) -> bool: """ Ensures that platform and toolset are compatible (on Windows only): - - If no toolset is provided, a default is assigned based on the platform. + - If no toolset is provided, a default is assigned based on the host platform. - If an invalid combination is detected, the function returns False. - - On non-Windows platforms, the toolset (if specified) is ignored with a warning. + - On non-Windows host platforms, the toolset (if specified) is ignored with a warning. Args: cfg (Config): The configuration object. @@ -305,8 +363,12 @@ def wwise_platform_and_toolset_compatible(cfg) -> bool: Returns: bool: True if compatible, False if an invalid combination is detected. """ - - if (platform.system() == "Windows"): + if cfg.crossCompilationEnabled: + system = cfg.wwise_platform + else: + system = platform.system() + + if (system == "Windows"): default_toolset = "vc170" # Strict compatibility @@ -424,3 +486,49 @@ def run_system_command(cmd : List[str], error_code:Optional[int]=None) -> subpro print(e.stderr.strip()) print(f"Exiting with error code {error_code or e.returncode}") sys.exit(error_code or e.returncode) + +def get_installation_location(cfg) -> str: + """ + Determines the installation location for the generated plugin. + + Returns: + str: The installation path for the plugin. + """ + if cfg.crossCompilationEnabled: + if cfg.wwise_platform == "Android": + + wwise_arch = "" if (cfg.wwise_arch is None) else cfg.wwise_arch + + if platform.system() == "Windows": + return os.path.join( + cfg.wwiseroot, + 'SDK\Android_' + wwise_arch, + cfg.wwise_configuration, + 'bin', + "lib" + cfg.plugin_name + ".so" + ) + else: + return cfg.build_location + else: + return cfg.build_location + + if cfg.wwise_platform in ["Authoring", "Authoring_Windows", "Windows_vc160", "Windows_vc170"]: + return os.path.join( + cfg.wwiseroot, + 'Authoring', + cfg.wwise_arch, + cfg.wwise_configuration, + 'bin', + 'Plugins', + cfg.plugin_name + ) + ".(ext)" + + if cfg.wwise_platform == "Mac": + return os.path.join( + cfg.wwiseroot, + "SDK", + "Mac_Xcode", + cfg.wwise_configuration, + "bin", + "lib" + cfg.plugin_name + ".dylib" + ) \ No newline at end of file diff --git a/architecture/wwise/xmlinjector.py b/architecture/wwise/xmlinjector.py index 026dbfcb02..a7b8e86571 100644 --- a/architecture/wwise/xmlinjector.py +++ b/architecture/wwise/xmlinjector.py @@ -69,8 +69,8 @@ def _parameter_to_property_xml(param) -> ET.Element: if param.is_slider(): ET.SubElement(property_elem, "UserInterface", { "Step": str(param.step), - "Fine": "0.1", - "Decimals": "1", + "Fine": str(param.step), + "Decimals": str(param.num_decimals), "UIMax": str(param.max or 1000) }) diff --git a/tools/faust2appls/faust2wwise.py b/tools/faust2appls/faust2wwise.py index 4baf4fbfec..32a06adfea 100644 --- a/tools/faust2appls/faust2wwise.py +++ b/tools/faust2appls/faust2wwise.py @@ -112,11 +112,11 @@ def import_module(faust_dsp_dir:str, file:str)-> Optional[ModuleType]: spec.loader.exec_module(module) return module -def print_message_on_fail() -> None: +def print_message_on_fail(link_to_troubleshooting_guide: str) -> None: print("\nAn error occurred during execution.") print("Please review the console output above to identify the issue.") print("For help, refer to the Troubleshooting Guide:") - print("\thttps://github.com/grame-cncm/faust/blob/master-dev/architecture/wwise/README.md#troubleshooting") + print(f"\t{link_to_troubleshooting_guide}") print("If the error is not listed there, check the GitHub issues or consider reporting it:") print("\thttps://github.com/grame-cncm/faust/issues") @@ -130,6 +130,13 @@ def print_message_on_abort() -> None: print("Please ensure Wwise and Faust are properly installed and configured.") sys.exit(1) # ERR_ENV_VARS_NOT_FOUND +def print_environment_summary() -> None: + print("\n--------- Environment variables ----------\n") + print("Wwise installation:", wwise_root_dir or "Not found") + print(f"faust_dsp_dir {faust_dsp_dir}") + print(f"faust_include_dir {faust_include_dir}") + print("\n------------------------------------------\n") + if __name__ == "__main__": wwise_root_dir = get_wwise_root_dir() @@ -139,33 +146,67 @@ def print_message_on_abort() -> None: if None in (wwise_root_dir, faust_dsp_dir, faust_include_dir): print_message_on_abort() - print(f"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") - print(f"faust2wwise static compilation tool.") - print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n") - - print("\n--------- Environment variables ----------\n") - print("Wwise installation:", wwise_root_dir or "Not found") - print(f"faust_dsp_dir {faust_dsp_dir}") - print(f"faust_include_dir {faust_include_dir}") - print("\n------------------------------------------\n") - if ("test" in sys.argv): + print(f"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + print(f"faust2wwise static compilation testing tool.") + print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n") + print_environment_summary() + test_module = import_module(faust_dsp_dir,"test.py") tester = test_module.TestFaustExamples( wwiseroot = wwise_root_dir) tester.test_faust2wwise() + elif ("interpreter-install" in sys.argv): + + print(f"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + print(f"faust2wwise dynamic compilation plugin installation.") + print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n") + print_environment_summary() + + interpreter_module = import_module(faust_dsp_dir,"faustinterpreter.py") + + installer = interpreter_module.PluginInstaller( \ + wwiseroot = wwise_root_dir, + faust_dsp_dir = faust_dsp_dir, + faust_include_dir = faust_include_dir) + + link_to_troubleshooting_guide = "https://github.com/grame-cncm/faust/blob/master-dev/architecture/wwise/Faust_Interpreter_Wwise_Plugin/README.md#troubleshooting" + + try: + + installer.install_interpreter() + + except SystemExit as e: + + if e.code!=0: + print_message_on_fail(link_to_troubleshooting_guide) + sys.exit(e.code) + + except: + + print("Exiting faust2wwise with error code 1 : Missing or inaccessible environment variables or system calls.") + print_message_on_fail(link_to_troubleshooting_guide) + sys.exit(1) + else: + print(f"\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + print(f"faust2wwise static compilation testing tool.") + print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n") + print_environment_summary() + orchestrator_module = import_module(faust_dsp_dir,"orchestrator.py") faust2wwiser = orchestrator_module.Faust2WwiseOrchestrator( \ wwiseroot = wwise_root_dir, faust_dsp_dir = faust_dsp_dir, faust_include_dir = faust_include_dir) - + + link_to_troubleshooting_guide = "https://github.com/grame-cncm/faust/blob/master-dev/architecture/wwise/README.md#troubleshooting" + try: faust2wwiser.orchestrate() @@ -173,11 +214,11 @@ def print_message_on_abort() -> None: except SystemExit as e: if e.code!=0: - print_message_on_fail() + print_message_on_fail(link_to_troubleshooting_guide) sys.exit(e.code) except: print("Exiting faust2wwise with error code 1 : Missing or inaccessible environment variables or system calls.") - print_message_on_fail() + print_message_on_fail(link_to_troubleshooting_guide) sys.exit(1) \ No newline at end of file