{"id":38383770,"url":"https://github.com/warrengalyen/polyforce","last_synced_at":"2026-01-17T03:40:32.209Z","repository":{"id":216541720,"uuid":"738666440","full_name":"warrengalyen/polyforce","owner":"warrengalyen","description":"Subtractive polyphonic synthesizer made with Tone.js and Vue.js","archived":false,"fork":false,"pushed_at":"2024-01-11T19:16:55.000Z","size":1501,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-01-12T01:42:23.389Z","etag":null,"topics":["polyphonic","synth","synthesizer"],"latest_commit_sha":null,"homepage":"https://warrengalyen.github.io/polyforce/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/warrengalyen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2024-01-03T18:58:05.000Z","updated_at":"2024-01-11T00:57:24.000Z","dependencies_parsed_at":"2024-01-11T21:39:39.461Z","dependency_job_id":"171527a7-4305-44b9-a6fa-c5f898a51730","html_url":"https://github.com/warrengalyen/polyforce","commit_stats":null,"previous_names":["warrengalyen/polyforce"],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/warrengalyen/polyforce","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/warrengalyen%2Fpolyforce","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/warrengalyen%2Fpolyforce/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/warrengalyen%2Fpolyforce/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/warrengalyen%2Fpolyforce/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/warrengalyen","download_url":"https://codeload.github.com/warrengalyen/polyforce/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/warrengalyen%2Fpolyforce/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28493446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T02:39:23.645Z","status":"ssl_error","status_checked_at":"2026-01-17T02:34:19.649Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["polyphonic","synth","synthesizer"],"created_at":"2026-01-17T03:40:32.105Z","updated_at":"2026-01-17T03:40:32.195Z","avatar_url":"https://github.com/warrengalyen.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Polyforce \u003c!-- omit in toc --\u003e\n\nSubtractive polyphonic synthesizer built with Tone.js and Vue.js\n---\n\nRecommended browsers: Firefox | Chrome\n\n# Table of content \u003c!-- omit in toc --\u003e\n\n- [1. Project setup](#1-project-setup)\n- [2. Overview](#2-overview)\n  - [2.1. Introduction](#21-introduction)\n    - [2.1.1. Oscillators](#211-oscillators)\n    - [2.1.2. Filter](#212-filter)\n    - [2.1.3. Modulation](#213-modulation)\n    - [2.1.4. Master Effects](#214-master-effects)\n  - [2.2. Audio Path](#22-audio-path)\n  - [2.3. Controlling Knobs](#23-controlling-knobs)\n  - [2.4. Keyboard](#24-keyboard)\n  - [2.5. Controlling Presets](#25-controlling-presets)\n- [3. Components](#3-components)\n  - [3.1. Oscillator](#31-oscillator)\n  - [3.2. Mixer](#32-mixer)\n  - [3.3. Envelope Generators](#33-envelope-generators)\n  - [3.4. LFOs](#34-lfos)\n  - [3.5. Filter](#35-filter)\n  - [3.6. Master](#36-master)\n  - [3.7. Modulation Matrix](#37-modulation-matrix)\n  - [3.8. Oscilloscope](#38-oscilloscope)\n  - [3.9. Master Effects](#39-master-effects)\n    - [3.9.1. Distortion](#391-distortion)\n    - [3.9.2. Chorus](#392-chorus)\n    - [3.9.3. Delay](#393-delay)\n    - [3.9.4. Reverb](#394-reverb)\n    - [3.9.5. Limiter](#395-limiter)\n- [4. Tips on Reducing CPU Usage](#4-tips-on-reducing-cpu-usage)\n- [5. Technical Notes](#5-technical-notes)\n  - [5.1. Oscillator](#51-oscillator)\n  - [5.2. LFO](#52-lfo)\n  - [5.3. Envelope](#53-envelope)\n  - [5.4. Master Effects](#54-master-effects)\n  - [5.5. Modulation](#55-modulation)\n  - [5.6. Voice Management](#56-voice-management)\n- [6. References and inspiration](#6-references-and-inspiration)\n\n# 1. Project setup\n\nInstall dependencies:\n\n```js\nnpm install\n```\n\nRun command to compile and hot-reload for development:\n\n```js\nnpm run serve\n```\n\n# 2. Overview\n\n## 2.1. Introduction\n\nPolyforce is an 8-voices virtual polyphonic synthesizer designed for creating music in web browser.\n\n![synth][synth]\n\n### 2.1.1. Oscillators\n\nPolyforce houses 2 unison oscillators, which generate 4 basic waveforms:\n\n- sine\n- sawtooth\n- triangle\n- square\n\nEach oscillator is capable of producing 4 unison voices, adding up to a total 8 voices per note. With its 8 notes of polyphony this means you can play up to 64 voices simultaneously.\nPolyforce is equipped with additional one White Noise Generator.\n\n### 2.1.2. Filter\n\nFor sound shaping purposes Polyforce offers one filter with 3 basic types (lowpass, bandpass, lowpass), 2 rolloff slopes (12 and 24 dB/oct) and bypass mode.\n\n### 2.1.3. Modulation\n\nTo sculpt the sound Polyforce provides 2 polyphonic LFO's which can be used to modulate a whole set of different parameters. Next to it, it is possible to use the amplitude envelope and filter envelope as the source of modulation.\n\n### 2.1.4. Master Effects\n\nThe master effects section offers five sound effects:\n\n- Distortion - eight types of distortion;\n- Chorus - stereo chorus effect;\n- Delay - feedback delay effect;\n- Reverb - effect with adjustable size and pre-delay;\n- Limiter - brickwall limiter with adjustable threshold parameter for overload protection.\n\n## 2.2. Audio Path\n\nPolyforce is built on a classic *voice* architecture, that dynamically allocates a limited amount of voices during playtime. The scheme below shows the internal structure of the audio path of this synthesizer.\n\n![Structure of synthesizer][diagram]  \n\nThe advantage of this design is reduced demand for resources (a polyphonic synth does not need to provide a separate voice for every note, sort of playing them in parallel - vide [paraphonic synthesizer][1]), but, on the other hand, this approach forms a little additional overhead in creating logic for dynamic voices management.\n\n## 2.3. Controlling Knobs\n\nRotary knobs, faders and other controls can be controlled by clicking the handle and **dragging** up or down in the vertical direction. For higher accuracy hold the ***Shift*** key while dragging the mouse. The current knob value will be displayed for a short amount of time on the *preset display*.\n\n![Controlling Knobs][knobControl]  \nIf you want to know the exact value of a parameter, but you do not wish to change it, you can simply **click** a knob once. This will display its value on the screen without changing it.  \n**Double clicking** on a control resets its value to default.  \nTo speed up your workflow rotary knobs and sliders allow you to change its value using the **mouse wheel**.\n\n## 2.4. Keyboard\n\nPlaying piano notes with just a mouse is not ideal (or even possible for chords). However it is possible to use your desktop keyboard to trigger keys signals. The keyboard section at the bottom of the user interface consist of a 4-octave keyboard that will display stroked keys if the note does not exceed its range. Switching the current keyboard octave down and up is possible with keys **Z** and **X** respectively.\n\n## 2.5. Controlling Presets\n\nPolyforce is shipped with simple preset manager with option to preview pre-defined programs.  \n![Preset display][preset]  \n\nOn both sides of the display there are two buttons to change current preset to previous/next program respectively.\n\n# 3. Components\n\nIn this chapter each synthesizer components will be discussed one by one.\n\n## 3.1. Oscillator\n\n![Oscillator][oscillator]  \n\n***Wave***  \nValues: sine | sawtooth | triangle | square  \nBy dragging the waveform selector you can select of type to generate.\n\n***Octave***  \nRange: ± 3600 cents (±3 octaves)  \nTune oscillator voices up/down in octave range.\n\n***Seminote***  \nRange: ± 1200 cents (±12 seminotes)  \nTune oscillator voices up/down in seminotes range.\n\n***Finetune***  \nRange: ± 100 cents (±1 seminote)  \nFine-tune oscillator pitch voices between two half notes.\n\n***Phase***  \nRange: [0, 360]  \nChange start phase of waveform. This parameter does not have impact on wave, if *RETRIG* button is disabled.\n\n***Retrigger***  \nValues: on | off  \nForce all voices to start at the exact same location every time a new note is triggered. That location can be changed using the *Phase* knob.\n\n***Voices***  \nRange: [0, 4]  \nSelect number of generated unison voices. You can turn off oscillator by setting the number of voices to 0.\n\n## 3.2. Mixer\n\n![mixer][mixer]  \n\nThe mixer section allows you to control the level and panorama of oscillators 1-2 and Noise Generator.\n\n***Volume***  \nRange: [0, 1]  \nSet the output volume of the oscillator.\n\n***Pan***  \nRange: [-1, 1]  \nChange panorama of oscillator output to the left(-1) or right(1) channel.  \n\n## 3.3. Envelope Generators\n\nPolyforce offers two ADSR (Attack, Decay, Sustain, Release) envelopes:\n\n- Filter Env - controls filter frequency;\n- AMP Env - controls the progression of the volume of a sound;\n\n![eg][eg]  \n\nBoth work in the same manner and can be used as modulation souce in Modulation Matrix.\n\n***Attack***  \nRange: [1ms, 10s]  \nSpecifies the duration it takes for the amplitude envelope to go from zero to its maximum level.\n\n***Decay***  \nRange: [1ms, 10s]  \nSpecifies the duration of the decay stage, i.e. how long it takes the amplitude to fall back to the sustain level.\n\n***Sustain***  \nRange: [0, 1]  \nSpecifies the sustain level that is reached after the decay stage ends. The sustain stage lasts as long as a key is pressed.\n\n***Release***  \nRange: [1ms, 10s]  \nThis stage is reached whenever a key is released. This parameter specifies the duration it takes the envelope to hit zero.\n\n## 3.4. LFOs\n\nLow Frequency Oscillators are similar to Oscillators but they usally generate signal in an inaudible range used to continually change aspects of the sound, like modulating a volume or pitch.\n\n![lfo][lfo]  \n\n***Wave***  \nValues: sine | sawtooth | triangle | square  \nBy dragging the waveform selector you can select the type to generate.\n\n***Frequency***  \nRange: [0.2Hz, 10Hz]  \nChange pitch of oscillator.\n\n***Phase***  \nRange: [0, 360]  \nChange start phase of waveform. This parameter does not have an impact on wave, if *Retrig* button is disabled.\n\n***Retrigger***  \nValues: on | off  \nForce LFO to start at the exact same location every time a new note is triggered. That location can be changed using the *Phase* knob.\n\n***Gain***  \nValues: [0, 1]  \nSets the amplitude of LFO signal.\n\n## 3.5. Filter\n\n![filter][filter]  \n\n***Type***  \nValues: LP12 | LP24 | BP12 | BP24 | HP12 | HP24 | NONE  \nSpecifies type of filter:\n\n- LP (low-pass) filter damps frequencies above cutoff frequency;\n- BP (band-pass) filter damps frequencies around the cutoff frequency;\n- HP (high-pass) filter damps frequencies passes signal above the cutoff frequency unchanged.\n- NONE - allpass filter and that allows all frequencies to pass.  \n  \nNumbers next to filter type specify filter's rolloff slope as `dB per octave`, 12dB/oct and 24dB/oct respectively.\n\n***Cutoff***  \nRange: [20Hz, 20kHz]  \nThe most important parameter in the filter. Specifies the corner frequency where filter operates.\n\n***Resonance***  \nRange: [0, 10]  \nControls filter resonance at cutoff frequency. In Band-pass mode controls the width of the band. The width becomes narrower as the value increases.\n\n***Envelope***  \nRange: [0, 1]  \nControls how much the filter envelope affects the cutoff frequency. Set to zero, the filter envelope has no effect on the cutoff frequency. At 1 the envelope spans the entire cutoff range. If you want to set envelope amount to negative value use [Modulation Matrix](#modulation-matrix) instead with *Envelope* amount set to zero.\n\n## 3.6. Master\n\nThe master section is the last part of the audio path in the synthesizer before the signal is sent to your speakers.\nOn the right side of the Master panel is a VU meter which measures the output level. The red color indicates the signal is too loud and you should turn the volume down to prevent clipping.\n\n![master][master]  \n\n***Gain***  \nRange: [0, 1]  \nControls the overall volume of the entire synthesizer.\n\n***FX***  \nValues: on | off  \nToggle [Master Effects](#39-master-effects) section.\n\n## 3.7. Modulation Matrix\n\n![matrix][matrix]  \n\nThe Modulation Matrix allows you to create more complex patches by linking the selected source with one or more available parameters. It offers 5 slots that can be used to connect different parameters.  \nAll sources are converted to the same range: [0, 1] for unipolar and [-1, 1] for bipolar sources. The LFO's are bipolar, all other sources are unipolar. The current value of a source is **multiplied** with the *Amount* value [-1, 1] in the same modulation slot. The result of the multiplication is then **multiplied** again with selected parameter modulation range and **added** to destination value.\n\n## 3.8. Oscilloscope\n\n![scope][scope]  \n\nThe Oscilloscope display is hidden by default behind the Modulation Matrix and can be toggled by clicking on the button placed in top right corner of Matrix section. It displays the waveform shape on the synthesizer output in real time.\n\n## 3.9. Master Effects\n\nThe Master FX panel is hidden by default behind the keyboard and can be open by clicking on the *FX* button placed in the [*Master*](#36-master) section of the synthesizer, next to the [*Modulation Matrix*](#37-modulation-matrix).\n\n![fx][fx]  \n\nEach effect is shipped with an **ON/OFF** button placed in top right corner of each effect panel and a **WET** knob which controls the effect depth and sets the ratio between the wet and original input signal (except *Limiter* effect). A value of 0 will mute the effect, while a value of 1 will pass only the original - dry - signal.\n\n### 3.9.1. Distortion\n\nPolyforce offer eight types of waveshaping distortion algorithms:\n\n- Sine;\n- Gloubi Boulga *(waveshaping algorithm by Laurent de Soras)*;\n- Fold Back;\n- Soft Clip;\n- Saturation;\n- Bit Crusher;\n- Tarrabia *(waveshaping algorithm by Partice Tarrabia and Bram de Jong)*;\n- Fuzz.  \n  \nEach algorithm offers different sound and harmonic content. Switch between them by clicking on the display and selecting one from the dropdown list.\n\n***Amount***  \nRange: [0, 1]  \nControls the effect intensity.\n\n### 3.9.2. Chorus\n\nCreates an effect that sounds like multiple instruments being played simultaneously.\n\n***Delay***  \nRange: [2ms, 20ms]  \nThe output of chorus is a mix of the input signal with delayed copy of it. Controls the delay offset in miliseconds.\n\n***Depth***  \nRange: [0, 1]  \nControls internal LFO modulation intensity *(amplitude)*.\n\n***Feedback***  \nRange: [0, 1]  \nControls the amount of signal from the output that returns back into the input of the effect, which can be used to create a flanging effect.\n\n***Fequency***  \nRange: [10Hz, 10kHz]  \nControls the frequency of the LFO which modulates the *Delay* parameter.\n\n***Spread***  \nRange: [0, 180]  \nControls the amount of stereo spread. At 0, both LFO's will be panned centrally, while at 180, LFO's will be spread hard to left and right.\n\n### 3.9.3. Delay\n\nThe Feedback delay effect that can be used to create echoing sound effects.\n\n***Delay***  \nRange: [50ms, 1s]  \nControls delay time.\n\n***Feedback***  \nRange: [0, 1]  \nControls the speed with which the delays will fade away.\n\n### 3.9.4. Reverb\n\nThe Reverb effect simulates sound reflections from surrounding walls or objects. Make sound more realistic and add depth to it.\n\n***Size***  \nRange: [100ms, 5s]  \nControls the duration of effect. Larger values give perception of larger room.\n\n***Predelay***  \nRange: [100ms, 5s]  \nAdjusts the onset of the reverberated signal. Controls the amount of time before the reverb is fully ramped in.\n\n### 3.9.5. Limiter\n\nBrickwall limiter which limits the loudness of incoming signal.\n\n***Threshold***  \nRange: [-96dB, 0dB]  \nControls the level at which gain reduction begins.\n\n# 4. Tips on Reducing CPU Usage\n\nWhen using a lot of synthesizer and audio effects at the same time, CPU usage can become a problem. Here are some tips to reduce CPU usage:\n\n- **Envelope Generators**  \nTry to keep the *Decay* and *Release* parameters as small as possible. Sound with smaller release will fade faster and use less polyphony voices.\n- **Effects**  \n  Disable any master effects you don't use.\n- **Modulation Matrix**  \nClear unused sources and destinations slots from matrix. Synthesizer core will not process these nodes, if you do not need them. Even if you set *AMOUNT* parameter to 0, Polyforce will still send signals to connected nodes.\n- **Disable oscilloscope**  \nOscilloscope is generated in canvas element using *requestAnimationFrame* Web API method that allows to create high performance visual content, but require some additional resources. Disabling this element can significantly reduce CPU usage.\n- **Reduce polyphony usage**  \nPlaying complex chords is fun and Polyforce give you possibility to play up to 8 notes at the same time, but remember, it is just a JavaScript app, not highly optimized VST plugin designed to use in professional DAW's, but only in your web browser.\n\nIf you still experience any problems with this app try to reload the webpage or even close the current tab and wait a minute or so to let your browser clear its memory and cache on its own.\n\n---\n\n# 5. Technical Notes\n\nTone.js is an awesome framework that offers a bunch of high quality components, but for this project I decided to tweak some of them a little to provide additional functionalities.\nThis section explains (in short) the technical differences between Tone.js components and their customized implementations used in this project.\n\n## 5.1. Oscillator\n\n- add support for multiple detuning units, allows you to tune the oscillator easily to any note:\n  - octave - control pitch in octaves,\n  - seminote - control pitch in seminotes,\n  - finetune - control pitch in cents.\n- allow you to set voices number to zero and disable completely,\n- oscillator *free* phase mode - generate random phase for every new note, disable this effect, and sync all voices phase, by enabling *RETRIGGER* button.\n\n## 5.2. LFO\n\n- add retrigger switch - start LFO from the same phase position each note.\n\n## 5.3. Envelope\n\n- custom shape for decay curve - build in exponential curve sounds great with short decay values, its sharp and snappy, but the used algorithm is - IMHO - *too* sharp. Enlarging the decay value does not provide a significant change in sound amplitude, signal fades very fast and reaches sustain level very quickly. Project implementation uses an exponential function to shape the linear curve in the range [1, 0] slope which is next eased to fitthe  dedicated range using this formula:\n\n\u003cimg src=\"https://latex.codecogs.com/svg.latex?g(x,l,u)\u0026space;=\u0026space;f(\\frac{x-l}{u-l})(u-l)\u0026space;\u0026plus;\u0026space;l\" title=\"g(x,l,u) = f(\\frac{x-l}{u-l})(u-l) + l\" /\u003e\n\nwhere:  \nx - signal value,  \nu - upper signal value (1),  \nl - lower signal value (which is *sustain* value in range [0, 1])\n\n![decayeg][decayeg]\n*Custom envelope shape in comparison to built-in Tone.js Envelope with exponential decay curve. Settings values: decay time=1.5s, sustain=0.5, hold time=2s*.  \n\\\nCustom generated shape fades progressively in time and still does not sound as artificial as linear curve.\n\n## 5.4. Master Effects\n\n- disables effect in effect chain - Tone.js, for most of their effects components, provide only one parameter to control the effect intensity - *WET*. This parameter - however - does not prevent from using CPU usage, signal is still passed and processed by effect. Dedicated *ON/OFF* switch completely disconnect effect from audio chain and let orginal signal to pass through.\n\n## 5.5. Modulation\n\nTone.js (and Web Audio API in general) does not offer any native support of the independent control for a modulated parameter. Every parameter, connected to any modualation source, automatically recieves status ***overridden*** which prevents any value changes from being sent directly to this property. WAAPI architecture, however, allows you to connect multiple signals to one property where they are are summed together in the parameter input. Every modulatable parameter has been wrapped in a custom *MODULATION* function that provides dedicated input for a constant source value and modulation output. This way it has become possible to control the parameter base value independently from any modulation source connected to it.\n\nThe simplified implementation is presented on this diagram:\n\n```\nParameter Signal\n                ↘\n                (+) -→ Parameter\n                ↗\nModulation Signals\n```\n\nParameter can receive any modulation signal and sill be able to update its base value.\n\n## 5.6. Voice Management\n\nDue to the static and rigid nature of components relationships, I have decided to drop down the voice management system that the Tone.js *PolySynth* object has to offer, i.e. dynamic voice creation and removal of allocated voices. In the current implementation all polyphonic voices are initialized only once at start and allocated dynamically during playtime. This way the synthesizer can avoid potential latency time problems caused by expensive voice creation/initialization or removal, but at the overall cost of the synthesizer initialization time.\n\n# 6. References and inspiration\n\n- [Tone.js](https://tonejs.github.io/)\n- [Sound on Sound - Synth Secrets](https://www.soundonsound.com/techniques/whats-sound)\n- [Developing a Digital Synthesizer in C++ by Peter Goldsborough](https://issuu.com/petergoldsborough/docs/thesis_3c166f78d5673b)\n- [Musicdsp.org](https://www.musicdsp.org/en/latest/index.html)\n- [Making Audio Plugins - Martin Finke's Blog](http://www.martin-finke.de/blog/articles/)\n\n\u003c!-- links --\u003e\n  [1]: https://www.soundonsound.com/techniques/polyphony-digital-synths\n\n\u003c!-- images --\u003e\n  [synth]: media/synth.png?raw=true\n  [diagram]: media/diagram.png?raw=true\n  [knobControl]: media/controls.png?raw=true\n  [preset]: media/preset-display.png?raw=true\n  [eg]: media/eg.png?raw=true\n  [filter]: media/filter.png?raw=true\n  [matrix]: media/matrix.png?raw=true\n  [lfo]: media/lfo.png?raw=true\n  [mixer]: media/mixer.png?raw=true\n  [master]: media/master.png?raw=true\n  [oscillator]: media/oscillator.png?raw=true\n  [scope]: media/scope.png?raw=true\n  [fx]: media/fx.png?raw=true\n  [decayeg]: media/decayeg.png?raw=true\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwarrengalyen%2Fpolyforce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwarrengalyen%2Fpolyforce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwarrengalyen%2Fpolyforce/lists"}