├── docs ├── .nojekyll ├── styles.css ├── donate.html ├── install.html ├── index.html └── about.html ├── source ├── ttl-bronza │ ├── manifest.ttl │ └── bronza.ttl ├── ttl-metalluga │ ├── manifest.ttl │ └── metalluga.ttl ├── ttl-grelka │ ├── manifest.ttl │ └── grelka.ttl ├── ttl-charm │ ├── manifest.ttl │ └── charm.ttl ├── fx-resofilter.cpp ├── fx-resofilter.h ├── charm.cpp ├── grelka.cpp ├── bronza.cpp ├── metalluga.cpp ├── dsp.cpp └── dsp.h ├── README.md ├── LICENSE └── CMakeLists.txt /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /source/ttl-bronza/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | 5 | a lv2:Plugin ; 6 | lv2:binary ; 7 | rdfs:seeAlso . 8 | -------------------------------------------------------------------------------- /source/ttl-metalluga/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | 5 | a lv2:Plugin ; 6 | lv2:binary ; 7 | rdfs:seeAlso . 8 | -------------------------------------------------------------------------------- /docs/styles.css: -------------------------------------------------------------------------------- 1 | table { 2 | table-layout: fixed; 3 | border: 10px solid; 4 | border-style: outset; 5 | } 6 | 7 | td { 8 | padding: 15px; 9 | vertical-align:top; 10 | width: 45%; 11 | 12 | } 13 | 14 | 15 | .center { 16 | margin-left: auto; 17 | margin-right: auto; 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /source/ttl-grelka/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | a lv2:Plugin . 5 | 6 | lv2:binary . 7 | 8 | rdfs:seeAlso . 9 | 10 | 11 | 12 | a lv2:Plugin ; 13 | lv2:binary ; 14 | rdfs:seeAlso . 15 | -------------------------------------------------------------------------------- /source/ttl-charm/manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | 4 | a lv2:Plugin . 5 | 6 | lv2:binary . 7 | 8 | 9 | rdfs:seeAlso . 10 | 11 | 12 | 13 | 14 | a lv2:Plugin ; 15 | lv2:binary ; 16 | rdfs:seeAlso . 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bedroom Studio by Peter Semiletov 2 | A set of LV2 plugins for bedroom music studio :) The idea is to provide simple, nice sounding effects those become a legend. 3 | 4 | https://psemiletov.github.io/bedroomstudio/ 5 | 6 | Current plugins list: 7 | 8 | **Metalluga** - the hard and crips distortion with five controls to customize the effect for your needs: Drive, Level, Weigth, Resonance and Warmth. The main control here is Level, all other builds around it. If don't touch too much the distortion stuff, you can use Metalluga in more soft genres such as blues. 9 | 10 | **Bronza** - the plain fuzz pedal with two parameters - *Level* and *Fuzz*. Sounds like in sixties 11 | 12 | **Grelka Overdrive** - the classic overdrive, has Drive, Level, Lows and Treble parameters to define the sound. 13 | 14 | **Charm** - the saturation effect, makes sound more "analog". 15 | 16 | 17 | ## Build and install 18 | 19 | **Dependencies:** cmake, lv2 library 20 | 21 | **To build from the source:** 22 | 23 | ```mkdir b 24 | cmake .. 25 | make 26 | sudo make install 27 | ``` 28 | 29 | **To install from AUR** 30 | 31 | ``` 32 | yay -S bedroomstudio 33 | ``` 34 | 35 | ## Donate 36 | 37 | If you like this software, you can donate me to Paypal: peter.semiletov@gmail.com 38 | -------------------------------------------------------------------------------- /docs/donate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Bedroom Studio LV2 plugins 8 | 9 | 10 | 11 |

Bedroom Studio LV2 plugins

12 | 13 |

Public domain LV2 essential sound plugins

14 | 15 |

16 | Home | Главная • 17 | About | Инфа • 18 | Download | СкачатьDonate | Донат

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 33 | 34 | 35 | 36 | 37 |
27 | If you want to support the development, donate via Paypal: peter.semiletov@gmail.com 28 | 31 | Если вы хотите поддержать разработку, можете сделать это через Paypal: peter.semiletov@gmail.com 32 |
38 | 39 | 40 |

Made by Peter Semiletov | Создано Петром Семилетовым

41 | 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /source/fx-resofilter.cpp: -------------------------------------------------------------------------------- 1 | #include "fx-resofilter.h" 2 | 3 | /* 4 | Peter Semiletov, 2023 5 | */ 6 | 7 | 8 | /* 9 | this code based on Martin Finke's filter tutorial, 10 | where the filter itself based on the resonant filter 11 | by Paul Kellett http://www.musicdsp.org/showone.php?id=29 12 | */ 13 | 14 | 15 | float CResoFilter::process (float sample) 16 | { 17 | bufl0 += cutoff * (sample - bufl0 + feedback_amount * (bufl0 - bufl1)); //add reso 18 | bufl1 += cutoff * (bufl0 - bufl1); 19 | bufl2 += cutoff * (bufl1 - bufl2); 20 | bufl3 += cutoff * (bufl2 - bufl3); 21 | 22 | switch (mode) 23 | { 24 | case FILTER_MODE_LOWPASS: 25 | return bufl1; 26 | 27 | case FILTER_MODE_HIGHPASS: 28 | return sample - bufl0; 29 | 30 | case FILTER_MODE_BANDPASS: 31 | return bufl0 - bufl3; 32 | 33 | default: 34 | return 0.0f; 35 | } 36 | 37 | return 0.0f; 38 | } 39 | 40 | 41 | CResoFilter::CResoFilter() 42 | { 43 | cutoff = 0.99f; 44 | resonance = 0.0f; 45 | mode = FILTER_MODE_LOWPASS; 46 | 47 | bufl0 = 0.0f; 48 | bufl1 = 0.0f; 49 | bufl2 = 0.0f; 50 | bufl3 = 0.0f; 51 | bufr0 = 0.0f; 52 | bufr1 = 0.0f; 53 | bufr2 = 0.0f; 54 | bufr3 = 0.0f; 55 | 56 | calc_feedback_amount(); 57 | } 58 | 59 | 60 | void CResoFilter::reset() 61 | { 62 | bufl0 = 0.0f; 63 | bufl1 = 0.0f; 64 | bufl2 = 0.0f; 65 | bufl3 = 0.0f; 66 | bufr0 = 0.0f; 67 | bufr1 = 0.0f; 68 | bufr2 = 0.0f; 69 | bufr3 = 0.0f; 70 | 71 | calc_feedback_amount(); 72 | } 73 | -------------------------------------------------------------------------------- /source/fx-resofilter.h: -------------------------------------------------------------------------------- 1 | #ifndef FXRESOFILTER_H 2 | #define FXRESOFILTER_H 3 | 4 | 5 | /* 6 | Peter Semiletov, 2023 7 | */ 8 | 9 | /* 10 | this code based on Martin Finke's filter tutorial, https://www.martin-finke.de/articles/audio-plugins-013-filter/ 11 | 12 | where the filter itself based on the resonant filter 13 | by Paul Kellett http://www.musicdsp.org/showone.php?id=29 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | enum filter_mode 20 | { 21 | FILTER_MODE_LOWPASS = 0, 22 | FILTER_MODE_HIGHPASS, 23 | FILTER_MODE_BANDPASS 24 | }; 25 | 26 | 27 | class CResoFilter 28 | { 29 | public: 30 | 31 | float resonance; 32 | int mode; 33 | float feedback_amount; 34 | float cutoff; // filter.set_cutoff ((float) dsb_cutoff_freq / session samplerate); 35 | //actually, min 0.01, max 0.99, step 0.001 def 0.99 36 | //cutoff must be < 1.0 or will be div by zero at calc_feedback_amount 37 | 38 | float bufl0; 39 | float bufl1; 40 | float bufl2; 41 | float bufl3; 42 | float bufr0; 43 | float bufr1; 44 | float bufr2; 45 | float bufr3; 46 | 47 | CResoFilter(); 48 | 49 | void reset(); 50 | float process (float sample); 51 | 52 | inline void set_cutoff (float v) 53 | { 54 | if (cutoff == v) 55 | return; 56 | 57 | cutoff = v; 58 | calc_feedback_amount(); 59 | }; 60 | 61 | inline void set_resonance (float v) 62 | { 63 | if (resonance == v) 64 | return; 65 | 66 | resonance = v; 67 | calc_feedback_amount(); 68 | }; 69 | 70 | inline void calc_feedback_amount() {feedback_amount = resonance + (float) resonance / (1.0 - cutoff);}; 71 | }; 72 | 73 | 74 | #endif // FXRESOFILTER_H 75 | -------------------------------------------------------------------------------- /source/ttl-charm/charm.ttl: -------------------------------------------------------------------------------- 1 | # The full description of the plugin is in this file, which is linked to from 2 | # `manifest.ttl`. This is done so the host only needs to scan the relatively 3 | # small `manifest.ttl` files to quickly discover all plugins. 4 | 5 | @prefix doap: . 6 | @prefix foaf: . 7 | @prefix lv2: . 8 | @prefix rdf: . 9 | @prefix rdfs: . 10 | @prefix units: . 11 | 12 | 13 | a lv2:Plugin , 14 | lv2:DistortionPlugin ; 15 | 16 | doap:shortdesc "Warm sound saturator" ; 17 | doap:programming-language "C++" ; 18 | doap:name "Charm", 19 | "Шарм"@ru , 20 | "Charme"@fr; 21 | 22 | doap:maintainer [ 23 | foaf:name "Bedroom Studio" ; 24 | foaf:homepage ; 25 | foaf:mbox 26 | ] ; 27 | 28 | doap:license ; 29 | 30 | lv2:optionalFeature lv2:hardRTCapable ; 31 | 32 | lv2:port [ 33 | a lv2:AudioPort , 34 | lv2:InputPort ; 35 | lv2:index 0 ; 36 | lv2:symbol "in_l" ; 37 | lv2:name "In_Left" 38 | ] , 39 | 40 | [ 41 | a lv2:AudioPort , 42 | lv2:InputPort ; 43 | lv2:index 1 ; 44 | lv2:symbol "in_r" ; 45 | lv2:name "In_Right" 46 | ] , 47 | 48 | [ 49 | a lv2:AudioPort , 50 | lv2:OutputPort ; 51 | lv2:index 2 ; 52 | lv2:symbol "out_l" ; 53 | lv2:name "Out_Left" 54 | ], 55 | 56 | [ 57 | a lv2:AudioPort , 58 | lv2:OutputPort ; 59 | lv2:index 3 ; 60 | lv2:symbol "out_r" ; 61 | lv2:name "Out_Right" 62 | ], 63 | 64 | [ 65 | a lv2:InputPort , 66 | lv2:ControlPort ; 67 | lv2:index 4 ; 68 | lv2:symbol "charm" ; 69 | lv2:name "Charm" , 70 | "Charme"@fr , 71 | "Шарм"@ru ; 72 | lv2:default 0.50 ; 73 | lv2:minimum 0.0 ; 74 | lv2:maximum 1.0 ; 75 | units:unit units:coef ; 76 | ]. 77 | 78 | -------------------------------------------------------------------------------- /docs/install.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Bedroom Studio: Download and Install 8 | 9 | 10 | 11 |

Bedroom Studio LV2 plugins

12 | 13 |

Public domain LV2 essential sound plugins

14 | 15 |

16 | Home | Главная • 17 | About | Инфа • 18 | Download | СкачатьDonate | Донат

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 52 | 53 | 54 | 81 | 82 | 83 | 84 | 85 |
27 | 28 |

Download

29 | 30 |

project page on Github

31 | 32 |

Release 1.0.0

33 | 34 |

Install from AUR: yay -S bedroomstudio

35 | 36 | 37 |

Install from the source

38 | 39 | 40 |

Dependencies: cmake, lv2 library

41 | 42 |

To build from the source:

43 | 44 |

At the unpacked source directory, run

45 | 46 |
mkdir b
47 | cmake ..
48 | make
49 | sudo make install
50 | 51 |
55 | 56 | 57 |

Скачать

58 | 59 |

страница проекта на Github

60 | 61 |

Релиз 1.0.0

62 | 63 |

Установить из AUR: yay -S bedroomstudio

64 | 65 | 66 |

Установка из исходника:

67 | 68 | 69 |

Зависимости: cmake, lv2 library

70 | 71 |

Для сборки из исходника:

72 | 73 |

В распакованном каталоге с исходником, дайте команды

74 | 75 |
mkdir b
76 | cmake ..
77 | make
78 | sudo make install
79 | 80 |
86 | 87 |

Made by Peter Semiletov | Создано Петром Семилетовым

88 | 89 | 90 | -------------------------------------------------------------------------------- /source/ttl-bronza/bronza.ttl: -------------------------------------------------------------------------------- 1 | # The full description of the plugin is in this file, which is linked to from 2 | # `manifest.ttl`. This is done so the host only needs to scan the relatively 3 | # small `manifest.ttl` files to quickly discover all plugins. 4 | 5 | @prefix doap: . 6 | @prefix foaf: . 7 | @prefix lv2: . 8 | @prefix rdf: . 9 | @prefix rdfs: . 10 | @prefix units: . 11 | 12 | 13 | a lv2:Plugin , 14 | lv2:DistortionPlugin ; 15 | 16 | doap:shortdesc "Virtual fuzz box" ; 17 | doap:programming-language "C++" ; 18 | doap:name "Bronza", 19 | "Бронза"@ru ; 20 | 21 | doap:maintainer [ 22 | foaf:name "Bedroom Studio" ; 23 | foaf:homepage ; 24 | foaf:mbox 25 | ] ; 26 | 27 | doap:license ; 28 | 29 | lv2:optionalFeature lv2:hardRTCapable ; 30 | 31 | lv2:port [ 32 | a lv2:AudioPort , 33 | lv2:InputPort ; 34 | lv2:index 0 ; 35 | lv2:symbol "in" ; 36 | lv2:name "In" 37 | ] , [ 38 | a lv2:AudioPort , 39 | lv2:OutputPort ; 40 | lv2:index 1 ; 41 | lv2:symbol "out" ; 42 | lv2:name "Out" 43 | ], 44 | 45 | 46 | [ 47 | a lv2:InputPort , 48 | lv2:ControlPort ; 49 | lv2:index 2 ; 50 | lv2:symbol "level" ; 51 | lv2:name "Level" , 52 | "Уровень"@ru ; 53 | lv2:default 29.0 ; 54 | lv2:minimum 0.0 ; 55 | lv2:maximum 48.0 ; 56 | units:unit units:db ; 57 | lv2:scalePoint [ 58 | rdfs:label "+5" ; 59 | rdf:value 5.0 60 | ] , [ 61 | rdfs:label "0" ; 62 | rdf:value 0.0 63 | ] , [ 64 | rdfs:label "-5" ; 65 | rdf:value -5.0 66 | ] , [ 67 | rdfs:label "-10" ; 68 | rdf:value -10.0 69 | ] 70 | ], 71 | 72 | [ 73 | a lv2:InputPort , 74 | lv2:ControlPort ; 75 | lv2:index 3 ; 76 | lv2:symbol "fuzz" ; 77 | lv2:name "Fuzz" , 78 | "Фуз"@ru ; 79 | lv2:default 0.87 ; 80 | lv2:minimum 0.0 ; 81 | lv2:maximum 1.0 ; 82 | units:unit units:coef ; 83 | ]. 84 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Bedroom Studio LV2 plugins 8 | 9 | 10 | 11 |

Bedroom Studio LV2 plugins

12 | 13 |

Public domain LV2 essential sound plugins

14 | 15 |

16 | Home | Главная • 17 | About | Инфа • 18 | Download | СкачатьDonate | Донат

19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 49 | 50 | 51 | 72 | 73 | 74 | 75 | 76 |
30 | 31 |

NEWS

32 | 33 | 34 |

October 21 2023 - 1.0.0 release (GRUNGE SPIRIT).

35 | 36 |

First release introduces:

37 | 38 |

Metalluga - the hard and crips distortion with five controls to customize the effect for your needs: Drive, Level, Weigth, Resonanсe and Warmth. The main control here is Level, all other builds around it. If don't touch too much the distortion stuff, you can use Metalluga in more soft genres such as blues.

39 | 40 |

Bronza - the plain fuzz pedal with two parameters - Level and Fuzz. Sounds like in sixties.

41 | 42 |

Grelka Overdrive - the classic overdrive, has Drive, Level, Lows and Treble parameters to define the sound.

43 | 44 |

Charm - the saturation effect, makes sound more "analog".

45 | 46 | 47 | 48 |
52 | 53 |

НОВОСТИ

54 | 55 | 56 |

October 21 2023 - 1.0.0 release (GRUNGE SPIRIT).

57 | 58 |

Первая версия содержит:

59 | 60 | 61 |

Бронза - простой фуз с двумя параметрами - Уровень и Фуз. Звучание шестидесятых годов.

62 | 63 |

Грелка - классический овердрайв, имеет параметры Драйв, Уровень, Низы иВерха, позволяющие задать характер звучания.

64 | 65 |

Металлюга - тяжелый и четкий дисторшн с пятью параметрами: Драйв, Уровень, Тяжесть, Резонанс, Теплота, при помощи которых можно накрутить любой звучок. Основной параметр здесь Уровень, остальные строят искажения вокруг него. Если же отбросить в сторону накрутку дисторшна, можно использовать ее в более мягких жанрах, для приятного и полного тембра.

66 | 67 |

Шарм - простая примочка, придающая звуку аналоговую теплоту. Кстати, она встроена в конец цепочки обработки в Металлюге.

68 | 69 | 70 | 71 |
77 |
78 |

Made by Peter Semiletov | Создано Петром Семилетовым

79 | 80 | 81 | -------------------------------------------------------------------------------- /source/ttl-grelka/grelka.ttl: -------------------------------------------------------------------------------- 1 | # The full description of the plugin is in this file, which is linked to from 2 | # `manifest.ttl`. This is done so the host only needs to scan the relatively 3 | # small `manifest.ttl` files to quickly discover all plugins. 4 | 5 | @prefix doap: . 6 | @prefix foaf: . 7 | @prefix lv2: . 8 | @prefix rdf: . 9 | @prefix rdfs: . 10 | @prefix units: . 11 | 12 | 13 | a lv2:Plugin , 14 | lv2:DistortionPlugin ; 15 | 16 | doap:shortdesc "Virtual overdrive box" ; 17 | doap:programming-language "C++" ; 18 | doap:name "Grelka Overdrive", 19 | "Грелка"@ru ; 20 | 21 | doap:maintainer [ 22 | foaf:name "Bedroom Studio" ; 23 | foaf:homepage ; 24 | foaf:mbox 25 | ] ; 26 | 27 | doap:license ; 28 | 29 | lv2:optionalFeature lv2:hardRTCapable ; 30 | 31 | lv2:port [ 32 | a lv2:AudioPort , 33 | lv2:InputPort ; 34 | lv2:index 0 ; 35 | lv2:symbol "in" ; 36 | lv2:name "In" 37 | ] , [ 38 | a lv2:AudioPort , 39 | lv2:OutputPort ; 40 | lv2:index 1 ; 41 | lv2:symbol "out" ; 42 | lv2:name "Out" 43 | ], 44 | [ 45 | a lv2:InputPort , 46 | lv2:ControlPort ; 47 | lv2:index 2 ; 48 | lv2:symbol "drive" ; 49 | lv2:name "Drive" , 50 | "Драйв"@ru ; 51 | lv2:default 0.16 ; 52 | lv2:minimum 0.01 ; 53 | lv2:maximum 1.0 ; 54 | units:unit units:coef ; 55 | ], 56 | 57 | [ 58 | a lv2:InputPort , 59 | lv2:ControlPort ; 60 | lv2:index 3 ; 61 | lv2:symbol "level" ; 62 | lv2:name "Level" , 63 | "Уровень"@ru ; 64 | lv2:default 16.0 ; 65 | lv2:minimum -16.0 ; 66 | lv2:maximum 32.0 ; 67 | units:unit units:db ; 68 | lv2:scalePoint [ 69 | rdfs:label "+5" ; 70 | rdf:value 5.0 71 | ] , [ 72 | rdfs:label "0" ; 73 | rdf:value 0.0 74 | ] , [ 75 | rdfs:label "-5" ; 76 | rdf:value -5.0 77 | ] , [ 78 | rdfs:label "-10" ; 79 | rdf:value -10.0 80 | ] 81 | ], 82 | 83 | 84 | [ 85 | a lv2:InputPort , 86 | lv2:ControlPort ; 87 | lv2:index 4 ; 88 | lv2:symbol "hp" ; 89 | lv2:name "Lows" , 90 | "Низы"@ru ; 91 | lv2:default 200 ; 92 | lv2:minimum 40 ; 93 | lv2:maximum 1000 ; 94 | units:unit units:hz ; 95 | 96 | ], 97 | [ 98 | a lv2:InputPort , 99 | lv2:ControlPort ; 100 | lv2:index 5 ; 101 | lv2:symbol "lp" ; 102 | lv2:name "Treble" , 103 | "Верха"@ru ; 104 | lv2:default 13000 ; 105 | lv2:minimum 7000; 106 | lv2:maximum 16500 ; 107 | units:unit units:hz ; 108 | 109 | ]. 110 | -------------------------------------------------------------------------------- /docs/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Bedroom Studio LV2 plugins 8 | 9 | 10 | 11 |

Bedroom Studio LV2 plugins

12 | 13 |

Public domain LV2 essential sound plugins

14 | 15 |

16 | Home | Главная • 17 | About | Инфа • 18 | Download | СкачатьDonate | Донат

19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 47 | 48 | 49 | 71 | 72 | 73 | 74 | 75 |
27 | 28 |

GUITAR PEDALS

29 | 30 |

Guitar pedal effects from Bedroom Studio ARE NOT emulation of famous Boss DS-1, Boss Overdrive or Ibanez Tube Screamer. My effort is create its own, specific sound, altough it can be designed after hardware analogs. As LV2 plugins, you can use it at your preffered DAW: Ardor, Reaper, Muse, etc. 31 |

32 | 33 |

Bronza - the plain fuzz pedal with two parameters - Level and Fuzz. Sounds like in sixties.

34 | 35 |

Grelka Overdrive - the classic overdrive, has Drive, Level, Lows and Treble parameters to define the sound.

36 | 37 |

Metalluga - the hard and crips distortion with five controls to customize the effect for your needs: Drive, Level, Weigth, Resonance and Warmth. The main control here is Level, all other builds around it.If don't touch too much the distortion stuff, you can use Metalluga in more soft genres such as blues.

38 | 39 | 40 |

OTHER FX

41 | 42 |

Charm - simple, one-parameter saturator to add some warmth. BTW, it is built-in to Metalluga at the end of the chain.

43 | 44 | 45 | 46 |
50 | 51 |

ГИТАРНЫЕ ПРИМОЧКИ

52 | 53 |

Гитарные примочки из состава Bedroom Studio не эмулируют известные Boss DS-1, Boss Overdrive или Ibanez Tube Screamer. Моя задача несколько иная - создать своё особое звучание, хотя примочки могут быть созданы по мотивам аппаратных аналогов. 54 |

55 | 56 | 57 |

Бронза - простой фуз с двумя параметрами - Уровень и Фуз. Звучание шестидесятых годов.

58 | 59 |

Грелка - классический овердрайв, имеет параметры Драйв, Уровень, Низы и Верха, позволяющие задать характер звучания.

60 | 61 |

Металлюга - тяжелый и четкий дисторшн с пятью параметрами: Драйв, Уровень, Тяжесть, Резонанс, Теплота, при помощи которых можно накрутить любой звучок. Основной параметр здесь Уровень, остальные строят искажения вокруг него. Если же отбросить в сторону накрутку дисторшна, можно использовать ее в более мягких жанрах, для приятного и полного тембра.

62 | 63 | 64 | 65 |

ДРУГИЕ ЭФФЕКТЫ

66 | 67 |

Шарм - простая примочка, придающая звуку аналоговую теплоту. Кстати, она встроена в конец цепочки обработки в Металлюге.

68 | 69 | 70 |
76 |
77 |

Made by Peter Semiletov | Создано Петром Семилетовым

78 | 79 | 80 | -------------------------------------------------------------------------------- /source/ttl-metalluga/metalluga.ttl: -------------------------------------------------------------------------------- 1 | # The full description of the plugin is in this file, which is linked to from 2 | # `manifest.ttl`. This is done so the host only needs to scan the relatively 3 | # small `manifest.ttl` files to quickly discover all plugins. 4 | 5 | @prefix doap: . 6 | @prefix foaf: . 7 | @prefix lv2: . 8 | @prefix rdf: . 9 | @prefix rdfs: . 10 | @prefix units: . 11 | 12 | 13 | a lv2:Plugin , 14 | lv2:DistortionPlugin ; 15 | 16 | doap:shortdesc "Virtual distortion box" ; 17 | doap:programming-language "C++" ; 18 | doap:name "Metalluga", 19 | "Металлюга"@ru ; 20 | 21 | doap:maintainer [ 22 | foaf:name "Bedroom Studio" ; 23 | foaf:homepage ; 24 | foaf:mbox 25 | ] ; 26 | 27 | doap:license ; 28 | 29 | lv2:optionalFeature lv2:hardRTCapable ; 30 | 31 | lv2:port [ 32 | a lv2:AudioPort , 33 | lv2:InputPort ; 34 | lv2:index 0 ; 35 | lv2:symbol "in" ; 36 | lv2:name "In" 37 | ] , [ 38 | a lv2:AudioPort , 39 | lv2:OutputPort ; 40 | lv2:index 1 ; 41 | lv2:symbol "out" ; 42 | lv2:name "Out" 43 | ], 44 | [ 45 | a lv2:InputPort , 46 | lv2:ControlPort ; 47 | lv2:index 2 ; 48 | lv2:symbol "drive" ; 49 | lv2:name "Drive" , 50 | "Драйв"@ru ; 51 | lv2:default 0.50 ; 52 | lv2:minimum 0.0 ; 53 | lv2:maximum 1.0 ; 54 | units:unit units:coef ; 55 | ], 56 | 57 | [ 58 | a lv2:InputPort , 59 | lv2:ControlPort ; 60 | lv2:index 3 ; 61 | lv2:symbol "level" ; 62 | lv2:name "Level" , 63 | "Уровень"@ru ; 64 | lv2:default 0.0 ; 65 | lv2:minimum -90.0 ; 66 | lv2:maximum 32.0 ; 67 | units:unit units:db ; 68 | lv2:scalePoint [ 69 | rdfs:label "+5" ; 70 | rdf:value 5.0 71 | ] , [ 72 | rdfs:label "0" ; 73 | rdf:value 0.0 74 | ] , [ 75 | rdfs:label "-5" ; 76 | rdf:value -5.0 77 | ] , [ 78 | rdfs:label "-10" ; 79 | rdf:value -10.0 80 | ] 81 | ], 82 | 83 | [ 84 | a lv2:InputPort , 85 | lv2:ControlPort ; 86 | lv2:index 4 ; 87 | lv2:symbol "weigth" ; 88 | lv2:name "Weigth" , 89 | "Тяжесть"@ru ; 90 | lv2:default 0.68 ; 91 | lv2:minimum 0.01 ; 92 | lv2:maximum 0.99 ; 93 | units:unit units:coef ; 94 | 95 | ], 96 | 97 | [ 98 | a lv2:InputPort , 99 | lv2:ControlPort ; 100 | lv2:index 5 ; 101 | lv2:symbol "reso" ; 102 | lv2:name "Resonance" , 103 | "Резонанс"@ru ; 104 | lv2:default 0.50 ; 105 | lv2:minimum 0.01 ; 106 | lv2:maximum 0.99 ; 107 | units:unit units:coef ; 108 | 109 | ], 110 | 111 | [ 112 | a lv2:InputPort , 113 | lv2:ControlPort ; 114 | lv2:index 6 ; 115 | lv2:symbol "warmth" ; 116 | lv2:name "Warmth" , 117 | "Теплота"@ru ; 118 | lv2:default 0.50 ; 119 | lv2:minimum 0.01 ; 120 | lv2:maximum 0.99 ; 121 | units:unit units:coef ; 122 | 123 | ]. 124 | 125 | -------------------------------------------------------------------------------- /source/charm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | code is Public Domain and written by Peter Semiletov, 2023 3 | */ 4 | 5 | #include "lv2/core/lv2.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dsp.h" 14 | #include "fx-resofilter.h" 15 | 16 | #define CHARM_URI "https://github.com/psemiletov/charm" 17 | 18 | typedef enum { PORT_IN_LEFT = 0, PORT_IN_RIGHT = 1, PORT_OUT_LEFT = 2, PORT_OUT_RIGHT = 3, PORT_CHARM = 4} PortIndex; 19 | 20 | 21 | 22 | class CCharm 23 | { 24 | public: 25 | 26 | int samplerate; 27 | 28 | const float* charm; //warmth factor 29 | 30 | const float* input_l; 31 | const float* input_r; 32 | 33 | float *output_l; 34 | float *output_r; 35 | }; 36 | 37 | 38 | 39 | static void 40 | activate(LV2_Handle instance) 41 | {} 42 | 43 | 44 | static LV2_Handle 45 | instantiate (const LV2_Descriptor* descriptor, 46 | double rate, 47 | const char* bundle_path, 48 | const LV2_Feature* const* features) 49 | { 50 | init_db(); 51 | CCharm *instance = new CCharm; 52 | instance->samplerate = rate; 53 | 54 | return (LV2_Handle)instance; 55 | } 56 | 57 | 58 | static void 59 | connect_port (LV2_Handle instance, uint32_t port, void* data) 60 | { 61 | CCharm *inst = (CCharm*) instance; 62 | 63 | switch ((PortIndex) port) 64 | { 65 | case PORT_IN_LEFT: 66 | inst->input_l = (const float*)data; 67 | break; 68 | 69 | case PORT_IN_RIGHT: 70 | inst->input_r = (const float*)data; 71 | break; 72 | 73 | case PORT_OUT_LEFT: 74 | inst->output_l = (float*)data; 75 | break; 76 | 77 | case PORT_OUT_RIGHT: 78 | inst->output_r = (float*)data; 79 | break; 80 | 81 | case PORT_CHARM: 82 | inst->charm = (const float*)data; 83 | break; 84 | 85 | } 86 | } 87 | 88 | 89 | static void 90 | run (LV2_Handle instance, uint32_t n_samples) 91 | { 92 | CCharm *inst = (CCharm*) instance; 93 | 94 | for (uint32_t pos = 0; pos < n_samples; pos++) 95 | { 96 | float fl = inst->input_l[pos]; 97 | float fr = inst->input_r[pos]; 98 | 99 | fl = warmify (fl, *(inst->charm)); 100 | fr = warmify (fr, *(inst->charm)); 101 | 102 | inst->output_l[pos] = fl; 103 | inst->output_r[pos] = fr; 104 | } 105 | } 106 | 107 | 108 | static void deactivate (LV2_Handle instance) 109 | { 110 | } 111 | 112 | 113 | static void cleanup(LV2_Handle instance) 114 | { 115 | delete (CCharm*) instance; 116 | } 117 | 118 | 119 | static const void* extension_data (const char* uri) 120 | { 121 | return NULL; 122 | } 123 | 124 | 125 | static const LV2_Descriptor descriptor = {CHARM_URI, 126 | instantiate, 127 | connect_port, 128 | activate, 129 | run, 130 | deactivate, 131 | cleanup, 132 | extension_data}; 133 | 134 | 135 | LV2_SYMBOL_EXPORT 136 | const LV2_Descriptor* lv2_descriptor (uint32_t index) 137 | { 138 | return index == 0 ? &descriptor : NULL; 139 | } 140 | -------------------------------------------------------------------------------- /source/grelka.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | code is Public Domain and written by Peter Semiletov, 2023 3 | */ 4 | 5 | #include "lv2/core/lv2.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dsp.h" 14 | #include "fx-resofilter.h" 15 | 16 | #define GRELKA_URI "https://github.com/psemiletov/grelka" 17 | 18 | typedef enum { MTL_INPUT = 0, MTL_OUTPUT = 1, MTL_DRIVE = 2, MTL_LEVEL = 3, MTL_HPF = 4, MTL_LPF = 5} PortIndex; 19 | 20 | 21 | 22 | class CGrelka 23 | { 24 | public: 25 | 26 | int samplerate; 27 | 28 | CResoFilter hp; 29 | CResoFilter lp; 30 | 31 | const float* drive; 32 | const float* level; 33 | const float* lpf; 34 | const float* hpf; 35 | 36 | const float* input; 37 | float *output; 38 | 39 | CGrelka(); 40 | }; 41 | 42 | 43 | CGrelka::CGrelka() 44 | { 45 | hp.mode = FILTER_MODE_HIGHPASS; 46 | lp.reset(); 47 | hp.reset(); 48 | } 49 | 50 | 51 | static void 52 | activate(LV2_Handle instance) 53 | {} 54 | 55 | 56 | static LV2_Handle 57 | instantiate (const LV2_Descriptor* descriptor, 58 | double rate, 59 | const char* bundle_path, 60 | const LV2_Feature* const* features) 61 | { 62 | init_db(); 63 | CGrelka *instance = new CGrelka; 64 | instance->samplerate = rate; 65 | 66 | return (LV2_Handle)instance; 67 | } 68 | 69 | 70 | static void 71 | connect_port(LV2_Handle instance, uint32_t port, void* data) 72 | { 73 | CGrelka *inst = (CGrelka*)instance; 74 | 75 | switch ((PortIndex)port) 76 | { 77 | case MTL_INPUT: 78 | inst->input = (const float*)data; 79 | break; 80 | 81 | case MTL_OUTPUT: 82 | inst->output = (float*)data; 83 | break; 84 | 85 | case MTL_DRIVE: 86 | inst->drive = (const float*)data; 87 | break; 88 | 89 | case MTL_LEVEL: 90 | inst->level = (const float*)data; 91 | break; 92 | 93 | case MTL_LPF: 94 | inst->lpf = (const float*)data; 95 | break; 96 | 97 | case MTL_HPF: 98 | inst->hpf = (const float*)data; 99 | break; 100 | 101 | } 102 | } 103 | 104 | 105 | static void 106 | run(LV2_Handle instance, uint32_t n_samples) 107 | { 108 | CGrelka *inst = (CGrelka*)instance; 109 | 110 | inst->lp.set_cutoff ((float) *(inst->lpf) / inst->samplerate); 111 | inst->hp.set_cutoff ((float) *(inst->hpf) / inst->samplerate); 112 | 113 | for (uint32_t pos = 0; pos < n_samples; pos++) 114 | { 115 | float f = inst->input[pos]; 116 | 117 | f = overdrive (f, *(inst->drive), db2lin (*(inst->level))); 118 | 119 | f = inst->lp.process (f); 120 | f = inst->hp.process (f); 121 | 122 | inst->output[pos] = f; 123 | } 124 | } 125 | 126 | 127 | static void deactivate (LV2_Handle instance) 128 | { 129 | } 130 | 131 | 132 | static void cleanup(LV2_Handle instance) 133 | { 134 | delete (CGrelka*)instance; 135 | } 136 | 137 | 138 | static const void* extension_data (const char* uri) 139 | { 140 | return NULL; 141 | } 142 | 143 | 144 | static const LV2_Descriptor descriptor = {GRELKA_URI, 145 | instantiate, 146 | connect_port, 147 | activate, 148 | run, 149 | deactivate, 150 | cleanup, 151 | extension_data}; 152 | 153 | 154 | LV2_SYMBOL_EXPORT 155 | const LV2_Descriptor* lv2_descriptor (uint32_t index) 156 | { 157 | return index == 0 ? &descriptor : NULL; 158 | } 159 | -------------------------------------------------------------------------------- /source/bronza.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | code is Public Domain and written by Peter Semiletov, 2023 3 | */ 4 | 5 | #include "lv2/core/lv2.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dsp.h" 14 | #include "fx-resofilter.h" 15 | 16 | #define BRONZA_URI "https://github.com/psemiletov/bronza" 17 | 18 | typedef enum { MTL_INPUT = 0, MTL_OUTPUT = 1, MTL_LEVEL = 2, MTL_FUZZ = 3} PortIndex; 19 | 20 | 21 | 22 | class CBronza 23 | { 24 | public: 25 | 26 | int samplerate; 27 | 28 | CResoFilter lp; 29 | CResoFilter bhp; 30 | 31 | CResoFilter hp; 32 | CResoFilter bp; 33 | 34 | const float* level; 35 | const float* intensity; 36 | 37 | const float* input; 38 | float *output; 39 | 40 | CBronza(); 41 | }; 42 | 43 | 44 | CBronza::CBronza() 45 | { 46 | lp.reset(); 47 | 48 | bhp.reset(); 49 | bhp.mode = FILTER_MODE_HIGHPASS; 50 | 51 | bp.mode = FILTER_MODE_BANDPASS; 52 | bp.reset(); 53 | 54 | 55 | 56 | hp.mode = FILTER_MODE_HIGHPASS; 57 | hp.reset(); 58 | hp.set_cutoff (0.50); 59 | } 60 | 61 | 62 | static void 63 | activate(LV2_Handle instance) 64 | {} 65 | 66 | 67 | static LV2_Handle 68 | instantiate(const LV2_Descriptor* descriptor, 69 | double rate, 70 | const char* bundle_path, 71 | const LV2_Feature* const* features) 72 | { 73 | init_db(); 74 | CBronza *instance = new CBronza; 75 | instance->samplerate = rate; 76 | instance->lp.set_cutoff ( 12000 / rate); 77 | instance->hp.set_cutoff ( 500 / rate); 78 | 79 | return (LV2_Handle)instance; 80 | } 81 | 82 | 83 | static void 84 | connect_port(LV2_Handle instance, uint32_t port, void* data) 85 | { 86 | CBronza *inst = (CBronza*)instance; 87 | 88 | switch ((PortIndex)port) 89 | { 90 | case MTL_INPUT: 91 | inst->input = (const float*)data; 92 | break; 93 | 94 | case MTL_OUTPUT: 95 | inst->output = (float*)data; 96 | break; 97 | 98 | case MTL_LEVEL: 99 | inst->level = (const float*)data; 100 | break; 101 | 102 | case MTL_FUZZ: 103 | inst->intensity = (const float*)data; 104 | break; 105 | 106 | 107 | } 108 | } 109 | 110 | 111 | 112 | static void 113 | run(LV2_Handle instance, uint32_t n_samples) 114 | { 115 | CBronza *inst = (CBronza*)instance; 116 | 117 | // inst->bhp.set_cutoff ( (float) 40 / inst->samplerate); 118 | 119 | // inst->hp.set_cutoff (0.50f - *(inst->weight)); 120 | 121 | for (uint32_t pos = 0; pos < n_samples; pos++) 122 | { 123 | float f = inst->input[pos]; 124 | 125 | 126 | // f = inst->hp.process (f); 127 | 128 | 129 | // f = fuzz (f, db2lin (*(inst->level)), *(inst->intensity)); 130 | 131 | f = jimi_fuzz (f, db2lin (*(inst->level)), *(inst->intensity)); 132 | 133 | 134 | f = inst->lp.process (f); 135 | f = inst->hp.process (f); 136 | 137 | if (f > 1.0f) 138 | f = 1.0f; 139 | else 140 | if (f < -1.0f) 141 | f = -1.0f; 142 | 143 | 144 | 145 | inst->output[pos] = f; 146 | } 147 | } 148 | 149 | 150 | static void deactivate (LV2_Handle instance) 151 | { 152 | } 153 | 154 | 155 | static void cleanup(LV2_Handle instance) 156 | { 157 | delete (CBronza*)instance; 158 | } 159 | 160 | 161 | static const void* extension_data (const char* uri) 162 | { 163 | return NULL; 164 | } 165 | 166 | 167 | static const LV2_Descriptor descriptor = {BRONZA_URI, 168 | instantiate, 169 | connect_port, 170 | activate, 171 | run, 172 | deactivate, 173 | cleanup, 174 | extension_data}; 175 | 176 | 177 | LV2_SYMBOL_EXPORT 178 | const LV2_Descriptor* lv2_descriptor (uint32_t index) 179 | { 180 | return index == 0 ? &descriptor : NULL; 181 | } 182 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project (bedroomstudio VERSION 1.0.0 LANGUAGES CXX C) 3 | 4 | 5 | set(LV2_INSTALL_DIR lib/lv2 CACHE PATH "Specifies where the LV2 libraries should be installed") 6 | 7 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g -O2 ") 8 | 9 | 10 | option(USE_CLANG "Build with Clang" OFF) 11 | 12 | 13 | #add_definitions ( -DPIC ) 14 | 15 | if(USE_CLANG) 16 | set(CMAKE_CXX_COMPILER clang++) 17 | set(CMAKE_C_COMPILER clang) 18 | message("+ Build with Clang++") 19 | endif(USE_CLANG) 20 | 21 | 22 | find_package(PkgConfig) 23 | pkg_check_modules(LV2 REQUIRED lv2>=0.1.0) 24 | 25 | include_directories (${LV2_INCLUDE_DIRS}) 26 | link_directories (${LV2_LIBRARY_DIRS} ) 27 | 28 | 29 | 30 | add_library(metalluga SHARED 31 | ./source/dsp.cpp 32 | ./source/dsp.h 33 | ./source/fx-resofilter.h 34 | ./source/fx-resofilter.cpp 35 | ./source/metalluga.cpp 36 | ) 37 | 38 | add_library(grelka SHARED 39 | ./source/dsp.cpp 40 | ./source/dsp.h 41 | ./source/fx-resofilter.h 42 | ./source/fx-resofilter.cpp 43 | ./source/grelka.cpp 44 | ) 45 | 46 | 47 | add_library(bronza SHARED 48 | ./source/dsp.cpp 49 | ./source/dsp.h 50 | ./source/fx-resofilter.h 51 | ./source/fx-resofilter.cpp 52 | ./source/bronza.cpp 53 | ) 54 | 55 | 56 | add_library(charm SHARED 57 | ./source/dsp.cpp 58 | ./source/dsp.h 59 | ./source/charm.cpp 60 | ) 61 | 62 | 63 | add_library(flanger SHARED 64 | ./source/dsp.cpp 65 | ./source/dsp.h 66 | ./source/flanger.cpp 67 | ) 68 | 69 | add_library(eq SHARED 70 | ./source/dsp.cpp 71 | ./source/dsp.h 72 | ./source/eq.cpp 73 | ) 74 | 75 | 76 | set_target_properties(metalluga PROPERTIES PREFIX "") 77 | target_link_libraries(metalluga ${LV2_LIBRARIES}) 78 | 79 | set_target_properties(grelka PROPERTIES PREFIX "") 80 | target_link_libraries(grelka ${LV2_LIBRARIES}) 81 | 82 | set_target_properties(charm PROPERTIES PREFIX "") 83 | target_link_libraries(charm ${LV2_LIBRARIES}) 84 | 85 | set_target_properties(bronza PROPERTIES PREFIX "") 86 | target_link_libraries(bronza ${LV2_LIBRARIES}) 87 | 88 | set_target_properties(flanger PROPERTIES PREFIX "") 89 | target_link_libraries(flanger ${LV2_LIBRARIES}) 90 | 91 | set_target_properties(eq PROPERTIES PREFIX "") 92 | target_link_libraries(eq ${LV2_LIBRARIES}) 93 | 94 | 95 | 96 | # Metalluga install 97 | install(TARGETS metalluga 98 | LIBRARY 99 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/metalluga.lv2 100 | ) 101 | 102 | install (FILES ./source/ttl-metalluga/metalluga.ttl ./source/ttl-metalluga/manifest.ttl 103 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/metalluga.lv2 104 | ) 105 | 106 | 107 | # Grelka install 108 | install(TARGETS grelka 109 | LIBRARY 110 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/grelka.lv2 111 | ) 112 | 113 | install (FILES ./source/ttl-grelka/grelka.ttl ./source/ttl-grelka/manifest.ttl 114 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/grelka.lv2 115 | ) 116 | 117 | 118 | # Metalluga install 119 | install(TARGETS bronza 120 | LIBRARY 121 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/bronza.lv2 122 | ) 123 | 124 | install (FILES ./source/ttl-bronza/bronza.ttl ./source/ttl-bronza/manifest.ttl 125 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/bronza.lv2 126 | ) 127 | 128 | 129 | # Charm install 130 | install(TARGETS charm 131 | LIBRARY 132 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/charm.lv2 133 | ) 134 | 135 | install (FILES ./source/ttl-charm/charm.ttl ./source/ttl-charm/manifest.ttl 136 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/charm.lv2 137 | ) 138 | 139 | 140 | 141 | # Charm install 142 | install(TARGETS flanger 143 | LIBRARY 144 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/flanger.lv2 145 | ) 146 | 147 | install (FILES ./source/ttl-flanger/flanger.ttl ./source/ttl-flanger/manifest.ttl 148 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/flanger.lv2 149 | ) 150 | 151 | 152 | 153 | # Charm install 154 | install(TARGETS eq 155 | LIBRARY 156 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/eq.lv2 157 | ) 158 | 159 | install (FILES ./source/ttl-eq/eq.ttl ./source/ttl-eq/manifest.ttl 160 | DESTINATION ${CMAKE_INSTALL_PREFIX}/${LV2_INSTALL_DIR}/eq.lv2 161 | ) 162 | 163 | -------------------------------------------------------------------------------- /source/metalluga.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | code is Public Domain and written by Peter Semiletov, 2023 3 | */ 4 | 5 | #include "lv2/core/lv2.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dsp.h" 14 | #include "fx-resofilter.h" 15 | 16 | #define METALLUGA_URI "https://github.com/psemiletov/metalluga" 17 | 18 | typedef enum { MTL_INPUT = 0, MTL_OUTPUT = 1, MTL_DRIVE = 2, MTL_LEVEL = 3, MTL_WEIGHT = 4, MTL_RESO = 5, MTL_WARMTH = 6} PortIndex; 19 | 20 | 21 | 22 | class CMetalluga 23 | { 24 | public: 25 | 26 | int samplerate; 27 | 28 | CResoFilter lp; 29 | CResoFilter hp; 30 | 31 | const float* drive; 32 | const float* level; 33 | const float* weight; 34 | const float* reso; 35 | const float* warmth; 36 | 37 | const float* input; 38 | float *output; 39 | 40 | CMetalluga(); 41 | }; 42 | 43 | 44 | CMetalluga::CMetalluga() 45 | { 46 | hp.mode = FILTER_MODE_HIGHPASS; 47 | lp.reset(); 48 | hp.reset(); 49 | } 50 | 51 | 52 | static void 53 | activate(LV2_Handle instance) 54 | {} 55 | 56 | 57 | static LV2_Handle 58 | instantiate(const LV2_Descriptor* descriptor, 59 | double rate, 60 | const char* bundle_path, 61 | const LV2_Feature* const* features) 62 | { 63 | init_db(); 64 | CMetalluga *instance = new CMetalluga; 65 | instance->samplerate = rate; 66 | 67 | return (LV2_Handle)instance; 68 | } 69 | 70 | 71 | static void 72 | connect_port(LV2_Handle instance, uint32_t port, void* data) 73 | { 74 | CMetalluga *inst = (CMetalluga*)instance; 75 | 76 | switch ((PortIndex)port) 77 | { 78 | case MTL_INPUT: 79 | inst->input = (const float*)data; 80 | break; 81 | 82 | case MTL_OUTPUT: 83 | inst->output = (float*)data; 84 | break; 85 | 86 | case MTL_DRIVE: 87 | inst->drive = (const float*)data; 88 | break; 89 | 90 | case MTL_LEVEL: 91 | inst->level = (const float*)data; 92 | break; 93 | 94 | case MTL_WEIGHT: 95 | inst->weight = (const float*)data; 96 | break; 97 | 98 | case MTL_RESO: 99 | inst->reso = (const float*)data; 100 | break; 101 | 102 | case MTL_WARMTH: 103 | inst->warmth = (const float*)data; 104 | break; 105 | 106 | } 107 | } 108 | 109 | 110 | static void 111 | run(LV2_Handle instance, uint32_t n_samples) 112 | { 113 | CMetalluga *inst = (CMetalluga*)instance; 114 | 115 | //const float* const input = inst->input; 116 | //float* const output = inst->output; 117 | 118 | for (uint32_t pos = 0; pos < n_samples; pos++) 119 | { 120 | 121 | float f = inst->input[pos]; 122 | 123 | f *= db2lin (*(inst->level)); 124 | 125 | f = gritty_guitar_distortion(f, *(inst->drive)); 126 | 127 | inst->lp.set_cutoff (1 - *(inst->weight)); 128 | inst->hp.set_cutoff (1 - *(inst->weight)); 129 | 130 | f = inst->lp.process (f); 131 | f = inst->hp.process (f); 132 | 133 | f = apply_resonance (f, *(inst->reso)); 134 | 135 | f = warmify (f, *(inst->warmth)); 136 | 137 | inst->output[pos] = f; 138 | } 139 | } 140 | 141 | 142 | static void deactivate (LV2_Handle instance) 143 | { 144 | } 145 | 146 | 147 | static void cleanup(LV2_Handle instance) 148 | { 149 | delete (CMetalluga*)instance; 150 | } 151 | 152 | 153 | static const void* extension_data (const char* uri) 154 | { 155 | return NULL; 156 | } 157 | 158 | 159 | static const LV2_Descriptor descriptor = {METALLUGA_URI, 160 | instantiate, 161 | connect_port, 162 | activate, 163 | run, 164 | deactivate, 165 | cleanup, 166 | extension_data}; 167 | 168 | 169 | LV2_SYMBOL_EXPORT 170 | const LV2_Descriptor* lv2_descriptor (uint32_t index) 171 | { 172 | return index == 0 ? &descriptor : NULL; 173 | } 174 | -------------------------------------------------------------------------------- /source/dsp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Peter Semiletov, 2023 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "dsp.h" 9 | 10 | 11 | using namespace std; 12 | 13 | 14 | float db_scale; 15 | 16 | void init_db() 17 | { 18 | /* 19 | #if defined(__clang__) 20 | // 21 | #elif defined(__GNUC__) || defined(__GNUG__) 22 | 23 | unsigned int mxcsr = __builtin_ia32_stmxcsr (); 24 | mxcsr |= MXCSR_DAZ | MXCSR_FTZ; 25 | __builtin_ia32_ldmxcsr (mxcsr); 26 | 27 | #elif defined(_MSC_VER) 28 | // 29 | #endif 30 | */ 31 | 32 | db_scale = log (10.0) * 0.05; 33 | } 34 | 35 | 36 | 37 | /*************** SATURATION/DIST/OVERDRIVE *******************/ 38 | 39 | #include 40 | 41 | 42 | 43 | float jimi_fuzz (float input_sample, float level, float distortion) 44 | { 45 | // Этап 1: Гиперболическое искажение 46 | float hyperbolic_sample = tanh (input_sample * distortion); 47 | 48 | // Этап 2: Насыщение 49 | float saturated_sample = hyperbolic_sample * 0.7f; // Уменьшаем амплитуду для насыщения 50 | 51 | // Этап 3: Применение "ламповости" 52 | float lamp_sample = (1.0f - expf(-fabs (saturated_sample))) * (saturated_sample >= 0 ? 1 : -1); 53 | 54 | // Умножаем на уровень для настройки громкости 55 | float output_sample = lamp_sample * level; 56 | 57 | if (output_sample > 1.0f) 58 | output_sample = 1.0f; 59 | else 60 | if (output_sample < -1.0f) 61 | output_sample = -1.0f; 62 | 63 | 64 | return output_sample; 65 | } 66 | 67 | /* 68 | float fuzz (float input, float level, float intensity) 69 | { 70 | float distorted = sin (input) + intensity * sin (input * 12.0f); 71 | 72 | // Уровень выхода 73 | distorted *= level; 74 | 75 | 76 | if (distorted > 1.0f || distorted < -1.0f) 77 | distorted /= 2; 78 | 79 | // Ограничиваем выходное значение в диапазоне от -1 до 1 80 | if (distorted > 1.0f) { 81 | distorted = 1.0f; 82 | } else if (distorted < -1.0f) { 83 | distorted = -1.0f; 84 | } 85 | 86 | 87 | return distorted; 88 | } 89 | */ 90 | 91 | float overdrive (float input, float drive, float level) 92 | { 93 | // float output = std::sin(input * 2.0f * 3.14159265359f); // Примерный алгоритм, можно настроить под нужное звучание 94 | float output = std::atan (input * 3.0f * 3.14159265359f); // Примерный алгоритм, можно настроить под нужное звучание 95 | 96 | output *= drive; // Уровень искажения зависит от параметра drive 97 | 98 | // Применяем предварительное усиление 99 | output *= level; 100 | 101 | 102 | // Ограничиваем выходное значение в пределах [-1, 1] 103 | if (output > 1.0f) 104 | output = 1.0f; 105 | else 106 | if (output < -1.0f) 107 | output = -1.0f; 108 | 109 | 110 | return output; 111 | } 112 | 113 | 114 | // Функция для "хриплого" гитарного искажения 115 | float gritty_guitar_distortion (float input_sample, float distortion_level) 116 | { 117 | // Шаг 1: Усиление с более высоким коэффициентом 118 | float amplified_sample = input_sample * (1.5f + 4.0f * distortion_level); 119 | 120 | // Шаг 2: Операционный усилитель с более высокой нелинейностью 121 | float op_amp_output = tanh (2.0f * amplified_sample); 122 | 123 | // Шаг 3: Клиппер/ограничитель с более сильным искажением 124 | float clipped_sample = tanh (2.0f * op_amp_output); 125 | 126 | clipped_sample = std::min(1.0f, std::max(-1.0f, clipped_sample)); 127 | 128 | return clipped_sample; 129 | } 130 | 131 | 132 | //analog 133 | float warmify (float x, float warmth) 134 | { 135 | // Проверяем, что "warmth" находится в пределах от 0 до 1 136 | warmth = std::min (1.0f, std::max(0.0f, warmth)); 137 | 138 | // Применяем теплое, аналоговое воздействие на сигнал 139 | float warm_x = x * (1.0f - warmth) + std::sin(x * M_PI) * warmth; 140 | 141 | // Ограничиваем значения в диапазоне от -1 до 1 142 | warm_x = std::min(1.0f, std::max(-1.0f, warm_x)); 143 | 144 | return warm_x; 145 | } 146 | 147 | 148 | /*************** FILTERS *******************/ 149 | 150 | 151 | float hp_filter (float input, float samplerate, float fc) 152 | { 153 | // Рассчитываем константу времени T из частоты среза 154 | float T = 1.0f / (2.0f * M_PI * fc); 155 | 156 | // Рассчитываем коэффициент для фильтра 157 | float alpha = T / (T + 1.0f); 158 | 159 | // Инициализируем предыдущее значение (первоначальное условие) 160 | static float prev_output = 0.0f; 161 | 162 | // Применяем фильтр к входному сигналу 163 | float output = alpha * (prev_output + input - prev_output); 164 | 165 | // Обновляем предыдущее значение для следующего вызова 166 | prev_output = output; 167 | 168 | return output; 169 | } 170 | 171 | 172 | /*************** MISC *******************/ 173 | 174 | 175 | // Функция для мягкого понижения уровня сигнала, если он превышает порог в 18 дБ (выше нуля) 176 | 177 | const float thresholdLevel18db = pow (10.0f, 18.0f / 20.0f); // Значение, соответствующее +18 дБ 178 | 179 | 180 | float soft_limit (float input) 181 | { 182 | // Проверяем, превышает ли входной сигнал порог 183 | if (input > thresholdLevel18db) 184 | { 185 | // Рассчитываем множитель для понижения уровня 186 | float reduction_factor = thresholdLevel18db / input; 187 | 188 | // Применяем мягкое понижение уровня 189 | return input * reduction_factor; 190 | } 191 | 192 | // Если сигнал не превышает порог, возвращаем его без изменений 193 | return input; 194 | } 195 | 196 | 197 | 198 | float apply_resonance (float input, float resonance_amount) 199 | { 200 | // Вычисляем коэффициент для изменения резонанса 201 | float resonance_factor = 1.0f + resonance_amount; 202 | 203 | // Применяем резонансное изменение 204 | float resonant_signal = input * resonance_factor; 205 | 206 | // Ограничиваем результат в пределах от -1 до 1 (клиппинг) 207 | if (resonant_signal > 1.0f) 208 | resonant_signal = 1.0f; 209 | else 210 | if (resonant_signal < -1.0f) 211 | resonant_signal = -1.0f; 212 | 213 | 214 | return resonant_signal; 215 | } 216 | -------------------------------------------------------------------------------- /source/dsp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Peter Semiletov, 2023 3 | */ 4 | 5 | 6 | #ifndef DSP_H 7 | #define DSP_H 8 | /* 9 | #if defined(__clang__) 10 | // 11 | #elif defined(__GNUC__) || defined(__GNUG__) 12 | 13 | #define MXCSR_DAZ (1<<6) 14 | #define MXCSR_FTZ (1<<15) 15 | 16 | #elif defined(_MSC_VER) 17 | // 18 | #endif 19 | */ 20 | 21 | //#define _USE_MATH_DEFINES 22 | 23 | #include 24 | #include 25 | //#include 26 | #include 27 | #include 28 | 29 | #ifndef M_PI 30 | #define M_PI 3.14159265358979323846 31 | #endif 32 | 33 | 34 | #include 35 | 36 | class BaxandallEqualizer { 37 | public: 38 | float lowGain; // Уровень нижней полосы (-90 до +6 dB) 39 | float midGain; // Уровень средней полосы (-90 до +6 dB) 40 | float highGain; // Уровень верхней полосы (-90 до +6 dB) 41 | float lowFrequency; // Частота нижней полосы (Гц) 42 | float highFrequency; // Частота верхней полосы (Гц) 43 | 44 | BaxandallEqualizer() : lowGain(0), midGain(0), highGain(0), lowFrequency(100), highFrequency(10000) { 45 | recalculateCoeffs(); 46 | } 47 | 48 | void setSampleRate(float newSampleRate) { 49 | sampleRate = newSampleRate; 50 | recalculateCoeffs(); 51 | } 52 | 53 | void setLowGain(float gain) { 54 | lowGain = gain; 55 | recalculateCoeffs(); 56 | } 57 | 58 | void setMidGain(float gain) { 59 | midGain = gain; 60 | recalculateCoeffs(); 61 | } 62 | 63 | void setHighGain(float gain) { 64 | highGain = gain; 65 | recalculateCoeffs(); 66 | } 67 | 68 | float process(float inputSample) { 69 | // Применение эквалайзера 70 | float lowFiltered = lowCoeff * inputSample; 71 | float midFiltered = midCoeff * inputSample; 72 | float highFiltered = highCoeff * inputSample; 73 | 74 | // Выходное значение - комбинация трех полос 75 | return lowFiltered + midFiltered + highFiltered; 76 | } 77 | 78 | void recalculateCoeffs() { 79 | // Расчет коэффициентов для фильтрации 80 | float lowGainLinear = pow(10.0f, lowGain / 20.0f); 81 | float midGainLinear = pow(10.0f, midGain / 20.0f); 82 | float highGainLinear = pow(10.0f, highGain / 20.0f); 83 | 84 | lowCoeff = calculateCoeff(lowFrequency); 85 | midCoeff = calculateCoeff((lowFrequency + highFrequency) / 2.0f); 86 | highCoeff = calculateCoeff(highFrequency); 87 | 88 | lowCoeff *= lowGainLinear; 89 | midCoeff *= midGainLinear; 90 | highCoeff *= highGainLinear; 91 | } 92 | 93 | float calculateCoeff(float frequency) { 94 | float omega = 2.0f * M_PI * frequency / sampleRate; 95 | return (omega / (omega + 1.0f)); 96 | } 97 | 98 | float sampleRate = 44100.0f; // Начальное значение частоты дискретизации 99 | float lowCoeff = 1.0f; 100 | float midCoeff = 1.0f; 101 | float highCoeff = 1.0f; 102 | }; 103 | /* 104 | int main() { 105 | BaxandallEqualizer eq; 106 | 107 | // Изменение частоты дискретизации перед первым вызовом process 108 | eq.setSampleRate(48000.0f); 109 | 110 | // Установка уровней усиления 111 | eq.setLowGain(6.0f); // Усиление низких частот на +6 дБ 112 | eq.setMidGain(-6.0f); // Ослабление средних частот на -6 дБ 113 | eq.setHighGain(3.0f); // Усиление высоких частот на +3 дБ 114 | 115 | // Пример использования эквалайзера 116 | float inputSignal = 0.5f; // Входной сигнал 117 | float outputSignal = eq.process(inputSignal); 118 | 119 | return 0; 120 | } 121 | */ 122 | 123 | /* 124 | class BaxandallEqualizer { 125 | public: 126 | float lowGain; // Уровень нижней полосы (-90 до +6 dB) 127 | float midGain; // Уровень средней полосы (-90 до +6 dB) 128 | float highGain; // Уровень верхней полосы (-90 до +6 dB) 129 | float lowFrequency; // Частота нижней полосы (Гц) 130 | float highFrequency; // Частота верхней полосы (Гц) 131 | 132 | BaxandallEqualizer() : lowGain(0), midGain(0), highGain(0), lowFrequency(100), highFrequency(20000) { 133 | } 134 | 135 | void setSampleRate(float newSampleRate) { 136 | sampleRate = newSampleRate; 137 | } 138 | 139 | float process(float inputSample) { 140 | // Расчет коэффициентов для фильтрации 141 | float lowGainLinear = pow(10.0f, lowGain / 20.0f); 142 | float midGainLinear = pow(10.0f, midGain / 20.0f); 143 | float highGainLinear = pow(10.0f, highGain / 20.0f); 144 | 145 | float lowCoeff = calculateCoeff(lowFrequency); 146 | float midCoeff = calculateCoeff((lowFrequency + highFrequency) / 2.0f); 147 | float highCoeff = calculateCoeff(highFrequency); 148 | 149 | // Применение эквалайзера 150 | float lowFiltered = lowCoeff * lowGainLinear * inputSample; 151 | float midFiltered = midCoeff * midGainLinear * inputSample; 152 | float highFiltered = highCoeff * highGainLinear * inputSample; 153 | 154 | // Выходное значение - комбинация трех полос 155 | return lowFiltered + midFiltered + highFiltered; 156 | } 157 | 158 | private: 159 | float calculateCoeff(float frequency) { 160 | float omega = 2.0f * M_PI * frequency / sampleRate; 161 | return (omega / (omega + 1.0f)); 162 | } 163 | 164 | float sampleRate = 44100.0f; // Начальное значение частоты дискретизации 165 | }; 166 | 167 | 168 | */ 169 | 170 | /* 171 | class BaxandallEqualizer { 172 | public: 173 | float lowGain; // Уровень нижней полосы (-90 до +6 dB) 174 | float midGain; // Уровень средней полосы (-90 до +6 dB) 175 | float highGain; // Уровень верхней полосы (-90 до +6 dB) 176 | float lowFrequency; // Частота нижней полосы (Гц) 177 | float highFrequency; // Частота верхней полосы (Гц) 178 | 179 | BaxandallEqualizer() : lowGain(0), midGain(0), highGain(0), lowFrequency(100), highFrequency(10000) { 180 | } 181 | 182 | float process(float inputSample, float sampleRate) { 183 | // Расчет коэффициентов для нижней, средней и верхней полос эквалайзера 184 | float lowGainLinear = pow(10.0f, lowGain / 20.0f); 185 | float midGainLinear = pow(10.0f, midGain / 20.0f); 186 | float highGainLinear = pow(10.0f, highGain / 20.0f); 187 | 188 | float lowOmega = 2.0f * M_PI * lowFrequency / sampleRate; 189 | float midOmega = 2.0f * M_PI * (lowFrequency + highFrequency) / (2 * sampleRate); 190 | float highOmega = 2.0f * M_PI * highFrequency / sampleRate; 191 | 192 | // Расчет коэффициентов для фильтрации 193 | float lowCoeff = lowGainLinear / (1.0f + lowGainLinear); 194 | float midCoeff = midGainLinear / (1.0f + midGainLinear); 195 | float highCoeff = highGainLinear / (1.0f + highGainLinear); 196 | 197 | // Применение эквалайзера 198 | float lowFiltered = (1.0f - lowCoeff) * inputSample + lowCoeff * lowFilteredState; 199 | float midFiltered = (1.0f - midCoeff) * inputSample + midCoeff * midFilteredState; 200 | float highFiltered = (1.0f - highCoeff) * inputSample + highCoeff * highFilteredState; 201 | 202 | // Обновление состояний фильтров 203 | lowFilteredState = lowFiltered; 204 | midFilteredState = midFiltered; 205 | highFilteredState = highFiltered; 206 | 207 | // Выходное значение - комбинация трех полос 208 | return lowFiltered + midFiltered + highFiltered; 209 | } 210 | 211 | private: 212 | float lowFilteredState = 0.0f; 213 | float midFilteredState = 0.0f; 214 | float highFilteredState = 0.0f; 215 | }; 216 | 217 | */ 218 | 219 | 220 | class Flanger { 221 | public: 222 | // Конструктор. 223 | Flanger(float samplerate) { 224 | this->samplerate = samplerate; 225 | delay = 0.3; 226 | depth = 0.5; 227 | rate = 1; 228 | } 229 | 230 | // Устанавливает значение задержки. 231 | void set_delay(float delay) { 232 | this->delay = delay; 233 | } 234 | 235 | // Устанавливает значение глубины. 236 | void set_depth(float depth) { 237 | this->depth = depth; 238 | } 239 | 240 | // Устанавливает значение скорости изменения задержки. 241 | void set_rate(float rate) { 242 | this->rate = rate; 243 | } 244 | 245 | // Обрабатывает сэмпл сигнала. 246 | float process(float sample) { 247 | // Обновляем задержку. 248 | delay += rate / samplerate; 249 | 250 | // Вычисляем задержку в сэмплах. 251 | int delay_samples = delay * samplerate; 252 | 253 | // Создаем копию входного сигнала. 254 | std::vector copy = {sample}; 255 | 256 | // Применяем задержку к копии сигнала. 257 | for (int i = 1; i < delay_samples; i++) { 258 | copy.push_back(sample * delay); 259 | } 260 | 261 | // Смешиваем основной сигнал с задержанным сигналом. 262 | float mixed = sample; 263 | for (float delayed_sample : copy) { 264 | mixed += delayed_sample * depth; 265 | } 266 | 267 | // Возвращаем обработанный сэмпл. 268 | return mixed; 269 | } 270 | 271 | private: 272 | // Частота дискретизации. 273 | float samplerate; 274 | 275 | // Задержка. 276 | float delay; 277 | 278 | // Глубина. 279 | float depth; 280 | 281 | // Скорость изменения задержки. 282 | float rate; 283 | }; 284 | 285 | 286 | class FlangerEffect { 287 | public: 288 | 289 | int buffer_size; // Размер буфера задержки (можно настроить) 290 | 291 | float samplerate; 292 | float depth; 293 | float rate; 294 | float delay; 295 | float phase; 296 | float buffer [96000]; 297 | int index; 298 | 299 | FlangerEffect() 300 | { 301 | 302 | buffer_size = 96000; 303 | 304 | samplerate = 48000; 305 | delay = 300.0f; 306 | depth = 16; 307 | 308 | rate = 256; 309 | phase = 0.0f; 310 | //buffer = 0.0f 311 | index = 0; 312 | } 313 | 314 | float process(float input) { 315 | // Рассчитываем задержку в сэмплах 316 | float delay_samples = delay * 0.001f * samplerate; 317 | 318 | // Вычисляем значение LFO (низкочастотной осцилляции) 319 | // float lfo = depth * 0.5f * (1.0f - cos(2.0f * M_PI * rate * phase)); 320 | float lfo = depth * (1.0f - cos(3.0f * M_PI * rate * phase)); 321 | 322 | // Обновляем фазу LFO 323 | phase += 1.0f / samplerate; 324 | 325 | // Определяем позицию для чтения из буфера с задержкой 326 | int read_index = (index - static_cast(delay_samples + lfo)) % buffer_size; 327 | if (read_index < 0) { 328 | read_index += buffer_size; 329 | } 330 | 331 | // Записываем текущий вход в буфер и считываем задержанный сэмпл 332 | buffer[index] = input; 333 | float output = buffer[read_index]; 334 | 335 | // Обновляем индекс 336 | index = (index + 1) % buffer_size; 337 | 338 | return output; 339 | } 340 | 341 | 342 | }; 343 | 344 | 345 | 346 | 347 | 348 | extern float db_scale; 349 | 350 | inline float db2lin (float db) 351 | { 352 | return (float) exp (db * db_scale); 353 | } 354 | 355 | /* 356 | static inline float db2lin (float db) 357 | { 358 | return powf (10.0f, db / 20); 359 | } 360 | */ 361 | 362 | /* 363 | inline float float2db (float v) 364 | { 365 | if (v == 0.0f) 366 | return 0.0f; 367 | 368 | if (v > 0.0f) 369 | return (float) 20 * log10 (v / 1.0f); 370 | 371 | return (float) 20 * log10 (v / -1.0f); 372 | } 373 | */ 374 | 375 | void init_db(); 376 | 377 | 378 | 379 | /// 380 | 381 | inline bool float_greater_than (float a, float b) 382 | { 383 | return (a - b) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * std::numeric_limits::epsilon()); 384 | } 385 | 386 | 387 | inline bool float_less_than (float a, float b) 388 | { 389 | return (b - a) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * std::numeric_limits::epsilon()); 390 | } 391 | 392 | 393 | inline bool float_equal (float x, float y) 394 | { 395 | return std::abs(x - y) <= std::numeric_limits::epsilon() * std::abs(x); 396 | } 397 | 398 | /* 399 | inline float conv (float v, float middle, float max) 400 | { 401 | if (v == middle) 402 | return 0; 403 | 404 | if (v > middle) 405 | return (max - middle - v); 406 | else 407 | return middle - v; 408 | } 409 | 410 | 411 | inline float conv_to_db (float v, float v_min, float v_max, float range_negative, float range_positive) 412 | { 413 | if (v == 0) 414 | return 0; 415 | 416 | if (v > 0) 417 | { 418 | float x = v_max / range_positive; 419 | float y = v_max / v; 420 | return v / (y * x); 421 | } 422 | else 423 | { 424 | float x = v_min / range_negative; 425 | float y = v_min / v; 426 | 427 | return v / (y * x); 428 | } 429 | } 430 | */ 431 | 432 | inline float scale_val (float val, float from_min, float from_max, float to_min, float to_max) 433 | { 434 | return (val - from_min) * (to_max - to_min) / 435 | (from_max - from_min) + to_min; 436 | } 437 | 438 | 439 | #define PANLAW_SINCOS 0 440 | #define PANLAW_SQRT 1 441 | #define PANLAW_LINEAR0 2 442 | #define PANLAW_LINEAR6 3 443 | #define PANLAW_SINCOSV2 4 444 | 445 | 446 | //sin/cos panner, law: -3 dB 447 | #define PANMODE01 1 448 | inline void pan_sincos (float &l, float& r, float p) 449 | { 450 | float pan = 0.5f * M_PI * p; 451 | l = cos (pan); 452 | r = sin (pan); 453 | } 454 | 455 | 456 | //square root panner, law: -3 dB 457 | #define PANMODE02 2 458 | inline void pan_sqrt (float &l, float& r, float p) 459 | { 460 | l = sqrt (1 - p); 461 | r = sqrt (p); 462 | } 463 | 464 | 465 | //linear panner, law: 0 dB 466 | #define PANMODE03 3 467 | inline void pan_linear0 (float &l, float& r, float p) 468 | { 469 | l = 0.5f + (1 - p); 470 | r = 0.5f + p; 471 | } 472 | 473 | 474 | //linear panner, law: -6 dB 475 | #define PANMODE04 4 476 | inline void pan_linear6 (float &l, float& r, float p) 477 | { 478 | l = 1 - p; 479 | r = p; 480 | } 481 | 482 | 483 | inline void pan_sincos_v2 (float &l, float& r, float p) 484 | { 485 | float pan = p * M_PI / 2; 486 | l = l * sin (pan); 487 | r = r * cos (pan); 488 | } 489 | 490 | 491 | //power panner, law: -4.5 dB 492 | #define PANMODE05 5 493 | inline void pan_power45 (float &l, float& r, float p) 494 | { 495 | l = powf ((1 - p), 0.75) * l; 496 | r = powf (p, 0.75) * r; 497 | } 498 | 499 | //power panner, law: -1.5 dB 500 | // -1.5dB = 10^(-1.5/20) = 0.841395142 (power taper) 501 | #define PANMODE06 6 502 | inline void pan_power15 (float &l, float& r, float p) 503 | { 504 | l = powf ((1 - p), 0.25) * l; 505 | r = powf (p, 025) * r; 506 | } 507 | 508 | //equal power panner, law: -3 dB 509 | // -3dB = 10^(-3/20) = 0.707945784 510 | #define PANMODE07 7 511 | inline void pan_equal_power3 (float &l, float& r, float p) 512 | { 513 | l = sqrt (1 - p) * l; // = power((1-pan),0.5) * MonoIn; 514 | r = sqrt(p) * r; // = power(pan,0.5) * MonoIn 515 | } 516 | 517 | 518 | 519 | /*************** SATURATION/DIST/OVERDRIVE *******************/ 520 | 521 | float jimi_fuzz (float inputSample, float level, float distortion); 522 | //float fuzz (float input, float level, float intensity); 523 | float overdrive (float input, float drive, float level); 524 | float gritty_guitar_distortion (float input_sample, float distortion_level); 525 | float warmify (float x, float warmth); 526 | 527 | 528 | /*************** FILTERS *******************/ 529 | 530 | float hp_filter (float input, float samplerate, float fc); 531 | 532 | 533 | /*************** MISC *******************/ 534 | 535 | 536 | float soft_limit (float input); 537 | float apply_resonance (float input, float resonance_amount); 538 | 539 | 540 | #endif 541 | --------------------------------------------------------------------------------