199 |
200 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Binary synth
2 |
3 | _Audio synthesis from binary code of any file_
4 |
5 | [](https://bs.stranno.su) [](https://bs.stranno.su)
6 |
7 | **Demo**: https://bs.stranno.su
8 |
9 | **Video**: https://youtu.be/5LMYiLwfvRg?si=D9GdKJF3hmjvw4fg&t=654
10 |
11 | **Performance and lecture**: https://youtu.be/Vj476GVtHZU?si=y4QY3JSnzjmhn5ur
12 |
13 | **Article**: https://bs.stranno.su/drone-ambient-noise-synthesizer ([Dev.to](https://dev.to/max_alyokhin/drone-ambient-noise-synthesizer-in-javascript-when-instability-is-a-feature-not-a-bug-34i8) | [Habr](https://habr.com/ru/articles/970404))
14 |
15 | 
16 |
17 | _Эта страница есть также на русском_
18 |
19 | A web-synthesizer that generates sound from the binary code of any files (databending-instrument). It can synthesize sound directly in the browser, or be a generator of MIDI messages to external devices or DAWs, turning any file into a score. All the application code is written in Javascript and along with everything you need is packed into a single `.html`-file of about 450kb. The synthesizer doesn't need internet, it can be downloaded and run locally on any device with a browser.
20 |
21 | The application reads the file sequentially, and due to the high speed of reading and random deviation of reading duration, we can get quite unpredictable generation of timbre nuances, and at certain settings we can switch to granular synthesis.
22 |
23 | ## Quick start guide
24 |
25 | - open one of these links: [IDM](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22sine%22,%22gain%22:2.04,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:0,%22to%22:8},%22notesRange%22:{%22from%22:48,%22to%22:60},%22fragment%22:{%22from%22:0,%22to%22:5000},%22midiMode%22:false,%22biquadFilterFrequency%22:33.1,%22biquadFilterQ%22:112.4,%22LFO%22:{%22enabled%22:true,%22type%22:%22triangle%22,%22rate%22:34.5,%22depth%22:1},%22bitness%22:%2216%22,%22panner%22:-0.67,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:50,%22noMIDIPortsFound%22:true,%22velocity%22:120,%22solidMode%22:false,%22lastNoteOnMode%22:true}}) | [Ambient](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22triangle%22,%22gain%22:0.41,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:0,%22to%22:1},%22notesRange%22:{%22from%22:48,%22to%22:104},%22fragment%22:{%22from%22:0,%22to%22:624},%22midiMode%22:false,%22biquadFilterFrequency%22:39.3,%22biquadFilterQ%22:121.3,%22LFO%22:{%22enabled%22:true,%22type%22:%22sine%22,%22rate%22:99,%22depth%22:0.395},%22bitness%22:%228%22,%22panner%22:0,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:66,%22noMIDIPortsFound%22:true,%22velocity%22:66,%22solidMode%22:true,%22lastNoteOnMode%22:true}}) | [Harsh noise](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22sine%22,%22gain%22:2.56,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:41,%22to%22:90},%22notesRange%22:{%22from%22:48,%22to%22:104},%22fragment%22:{%22from%22:0,%22to%22:100720},%22midiMode%22:false,%22biquadFilterFrequency%22:418.5,%22biquadFilterQ%22:66.6,%22LFO%22:{%22enabled%22:true,%22type%22:%22sine%22,%22rate%22:91,%22depth%22:0.546},%22bitness%22:%228%22,%22panner%22:0.15,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:66,%22noMIDIPortsFound%22:true,%22velocity%22:66,%22solidMode%22:true,%22lastNoteOnMode%22:true}})
26 | - tap anywhere on the screen and upload any file (files are not sent anywhere, everything is computed on your device)
27 | - press the spacebar or the Play button
28 | - press and hold the `S` key and move the mouse. You can move the mouse indefinitely. Pressing `Esc` will return the cursor
29 | - with the `S` key held down, press `Shift` to “strengthen” or `Ctrl` to “weaken” the input
30 | - do similar actions with other settings by pressing the keys `Q`, `W`, `A`, `Z`, `X`, `C`, `V`, etc. (input fields have the corresponding key on the right side)
31 | - open several more tabs with the instrument in parallel and launch
32 | - move between tabs using `Ctrl + tab number` (9 max) or `Ctrl + Tab` / `Ctrl + Shift + Tab`
33 | - process the sound on-the-fly by connecting effects pedals, or by using Ableton or other DAWs and [Virtual audio cable](https://vac.muzychenko.net/en/)
34 | - switch to MIDI mode and control a virtual or external synthesizer using the [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)
35 | - save settings just by copying the URL or via Save settings button
36 | - copy the instrument to play without internet by right-clicking - Save As, or download from here from the folder `/dist`
37 |
38 | ## Contents
39 |
40 | - [Application principle](#principle)
41 | - [Switching to granular mode](#granular)
42 | - [Recommendations for optimal performance](#recommendation)
43 | - [MIDI](#midi)
44 | - [Interface features](#interface)
45 | - [Saving settings](#settings)
46 | - [Run locally and build the project](#run)
47 |
48 | ## Application principle
49 |
50 |
51 | All data on any computer or smartphone is in the form of files (which are, in essence, texts). The contents of these files are ultimately just zeros and ones. And these zeros and ones are basically all the same, so we need an interpreter to extract meaning from these texts. Basically, the file format (.mp3, .docx, etc.) is just a pointer to which interpreter we need to pass the text in order to extract meaning from it.
52 |
53 | But what if the file format and the interpreter don't match?
54 |
55 | In the case of musical experimentation, there have been earlier attempts, for example, to "play" a file through an audio editor.
56 |
57 | We could go further and write our own interpreter that would look at the files without regard to format, use its own "manner of reading" the original zeros and ones, and on that basis provide a complete system for controlled synthesis of sounds.
58 |
59 | 1. We can interpret files as an array of numbers. That is, we divide continuous machine code into _words_ of some information capacity (bitness):
60 |
61 | - 8 bits (numbers from 0 to 255)
62 | - 16 bits (numbers from 0 to 65 535)
63 |
64 | 2. Then, each word is a command that defines the frequency of the sound
65 |
66 | 3. At the level of the whole system, we set global parameters:
67 |
68 | - speed of interpretation
69 | - musical scale (or lack thereof), range of notes/frequencies
70 | - looping
71 | - MIDI mode
72 | - smooth or abrupt transition between commands
73 | - settings of virtual devices required for synthesis (oscillator, filter, LFO) or MIDI settings
74 |
75 | 4. To reduce the load on the device, we divide the file into chunks of 500 commands each
76 |
77 | 5. Recursively schedule the synthesis control by reading 500 instructions per iteration and using global parameters
78 |
79 | 6. If we have reached the end of the file, stop execution or start again
80 |
81 | ## Switching to granular mode
82 |
83 |
84 | > **Note**: Here and below the instrument interface terms are used. For their description, see below in the Interface features section
85 |
86 | Granular synthesis operates on small pieces of sounds — acoustic pixels. It is generally accepted that granular synthesis "starts" when operating with sounds <50ms. At values `fragment` * `reading speed` = <50 we begin to operate with acoustic pixels.
87 |
88 | In this case, each command from `fragment` can be considered a "subpixel", which, with `random time gap` enabled, is unique each time, and the pixel, respectively, is unique in multiples of the number of subpixels. As a result, we get a mutable timbre.
89 |
90 | In classical granular synthesis, pixels play simultaneously and in parallel, and their number can change over time. In BS, on the other hand, the pixels form a thread along which we move.
91 |
92 | *That is, in conventional granular synthesis, a truck with sand is thrown on the listener, where each grain of sand is an acoustic pixel, but here this sand is poured out through a funnel with the diameter of one grain of sand, and this thin stream is what we observe.*
93 |
94 | The image below shows the formation of an acoustic pixel from two commands (`fragment: from = 0, to = 1`), at a reading speed of 0.005 s. We need to consider that each frequency has a period *T*, equal to the ratio of a unit of time (1 second = 1000 milliseconds) to the frequency. This means that we can think of sound not only in terms of frequency, but also in terms of the time it takes for the wave to make one complete oscillation. If the wave does not have time to make a complete oscillation, such an object is called a "wavelet".
95 |
96 | 
97 |
98 | ## Recommendations for optimal performance
99 |
100 |
101 | - Use incognito mode with extensions disabled
102 | - Close the non-incognito browser
103 | - Leave only BS tabs in incognito mode
104 | - Use a separate browser [ungoogled-chromium](https://github.com/ungoogled-software/ungoogled-chromium), which uses a little less CPU and a lot less RAM.
105 |
106 | BS under workload requires on average up to 7.1% CPU, in incognito mode 6%, Firefox 4.2%, but runs less stable. Also the browser's open console/DevTools increases CPU consumption per tab by 10%. It is recommended to use BS in incognito mode without any other open tabs except BS tabs for maximum efficiency.
107 |
108 | More interesting sound is obtained with several independent instances of BS in different tabs. Theoretically, it would be possible to implement several BS threads in one tab, but this is less optimal, because browsers limit the maximum CPU usage per tab (in Chrome it is 10% of CPU). Also, each tab has its own [event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop). You can use `ctrl + tab number` to quickly switch between tabs.
109 |
110 | ## MIDI
111 |
112 |
113 | When the MIDI mode is enabled, the first available port and its first channel are automatically selected. Next, a `noteOn` signal is sent sequentially when reading, and a `noteOff` signal is sent after the `reading speed` time. In `continuous` mode, a `Pitch` signal is sent after each noteOn to hit the desired frequency.
114 |
115 | MIDI messages can be sent:
116 |
117 | - to neighboring tabs and browser windows if they are listening to MIDI (e.g., in the web analog [DX7](http://mmontag.github.io/dx7-synth-js))
118 | - in DAW and other applications with virtual synthesizers (i.e. BS can control, for example, synthesizer in Ableton).
119 | - to MIDI-compatible external devices connected to a computer
120 |
121 | To send MIDI messages to a DAW on Windows devices, you can use [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html).
122 |
123 | > **Note**: After any manipulations with MIDI ports (connection/disconnection/re-connection) it is necessary to completely restart the browser, closing all browser windows if there are several of them
124 |
125 | > **Note**: MIDI messages are generated on the desktop only
126 |
127 | ## Interface features
128 |
129 |
130 | - `Reading speed` — interpretation speed; at high speeds over 0.001 the application may become unstable
131 |
132 | - `Bitness` — we can divide the binary code into words of 8 or 16 bits, which changes the number of available frequencies (256 or 65536)
133 |
134 | - `Panner` — pan between left (-1) and right (1) channels
135 |
136 | - `Frequency generation mode`
137 |
138 | - `continuous` — continuous frequency distribution
139 | - `tempered` — distribution by 12-step equal-tempered scale. There are notes from C-2 to B8
140 |
141 | - `Transition type` — transition between frequencies
142 |
143 | - `immediate` — instantaneous, rough transition
144 | - `linear` — linearly to the next frequency
145 | - `exponential` — exponentially to the next frequency
146 |
147 | - `Random time gap` — adds a random amount of time to the next tone within the `reading speed` parameter. Makes the sound less "robotic", as the distance to each tone is slightly different and it adds more "liveliness" to the playing
148 |
149 | - `Fragment` — allows to play not the whole file, but a certain part of it
150 |
151 | - `Sample rate` — sampling frequency. In most cases it has little effect on the sound, but it is very important when playing at ultra-low frequencies like frequencies range 0 - 1
152 |
153 | - `Solid mode` — the "solid press" mode, does not send `noteOff` commands; if the commands are the same in a row (and as a consequence notes), even noteOn is not sent. `allSoundOff` is sent at the end. On some synthesizers it allows smooth transitions between notes
154 |
155 | - `Last noteOn mode` — leaves the last command in the loop pressed. Allows to make smoother transitions between repeats of patterns
156 |
157 | - Some input fields have a keyboard shortcut: pressing the corresponding key automatically moves the focus to the item. By pressing a key and moving the mouse at the same time, the values can be changed smoothly. Pressing `Shift` will increase (10x, 100x, 1000x) the "power" of the value change, pressing `Ctrl` will decrease (0.1x, 0.01x, 0.001x). The cursor disappears in order to be able to change values indefinitely. To return the cursor, press `Esc`
158 |
159 | ## Saving settings
160 |
161 |
162 | You can save your settings in two ways:
163 |
164 | - via a URL link. When you click in the address bar of your browser, the application automatically generates a link to which the settings are written. You can copy it and when you open the link, the settings will be applied immediately, all you have to do is download a file for sound synthesis.
165 | - through a file. The interface includes Save / Load / Restore settings buttons, which allow you to save or load a settings file to or from your computer and also restore initial settings.
166 |
167 | ## Run locally and build the project
168 |
169 |
170 | ### Just copy the app
171 |
172 | Everything you need for the system is contained in a single `.html` file, which you can download in the `dist` folder, or simply go to https://bs.ѕtranno.su and right-click and select Save As in the menu.
173 |
174 | ### Build locally to work with the code
175 |
176 | Tech stack: Vue3 + Pinia + Vite.
177 |
178 | 1. Download and install the LTS version of Node.js
179 | 2. Download the code directly from Github, or via `git clone`.
180 | 3. In the project folder in the terminal execute:
181 |
182 | ```bash
183 | npm i
184 | npm run dev # development-build
185 | npm run build # production-build, generate index.html with everything we need
186 | ```
187 |
188 | For MIDI tests, you can use this resource https://studiocode.dev/midi-monitor/
189 |
--------------------------------------------------------------------------------
/README_RU.md:
--------------------------------------------------------------------------------
1 | # Binary synth
2 |
3 | _Синтез аудио из двоичного кода любого файла_
4 |
5 | [](https://bs.stranno.su) [](https://bs.stranno.su)
6 |
7 | **Демо**: https://bs.stranno.su
8 |
9 | **Видео**: https://youtu.be/5LMYiLwfvRg?si=D9GdKJF3hmjvw4fg&t=654
10 |
11 | **Концерт и лекция**: https://youtu.be/Vj476GVtHZU?si=y4QY3JSnzjmhn5ur
12 |
13 | **Статья**: https://bs.stranno.su/drone-ambient-noise-synthesizer ([Dev.to](https://dev.to/max_alyokhin/drone-ambient-noise-synthesizer-in-javascript-when-instability-is-a-feature-not-a-bug-34i8) | [Habr](https://habr.com/ru/articles/970404))
14 |
15 | 
16 |
17 | Веб-синтезатор, генерирующий звук из двоичного кода любых файлов (databending-инструмент). Позволяет синтезировать звук прямо в браузере, либо быть генератором MIDI-сообщений во внешние устройства или DAW, превращая любой файл в партитуру. Весь код приложения написан на Javascript и вместе со всем необходимым упаковывается в один `.html`-файл размером около 450kb. Инструменту не нужен интернет, его можно скачать и запускать локально на любом устройстве где есть браузер.
18 |
19 | Приложение последовательно читает файл и за счёт высокой скорости чтения и случайной величины отклонения длительности чтения, можно получить достаточно непредсказуемую генерацию тембров, а при определённых настройках перейти в гранулярный синтез.
20 |
21 | ## Быстрый старт и краткое руководство
22 |
23 | - откройте одну из этих ссылок: [IDM](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22sine%22,%22gain%22:2.04,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:0,%22to%22:8},%22notesRange%22:{%22from%22:48,%22to%22:60},%22fragment%22:{%22from%22:0,%22to%22:5000},%22midiMode%22:false,%22biquadFilterFrequency%22:33.1,%22biquadFilterQ%22:112.4,%22LFO%22:{%22enabled%22:true,%22type%22:%22triangle%22,%22rate%22:34.5,%22depth%22:1},%22bitness%22:%2216%22,%22panner%22:-0.67,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:50,%22noMIDIPortsFound%22:true,%22velocity%22:120,%22solidMode%22:false,%22lastNoteOnMode%22:true}}) | [Ambient](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22triangle%22,%22gain%22:0.41,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:0,%22to%22:1},%22notesRange%22:{%22from%22:48,%22to%22:104},%22fragment%22:{%22from%22:0,%22to%22:624},%22midiMode%22:false,%22biquadFilterFrequency%22:39.3,%22biquadFilterQ%22:121.3,%22LFO%22:{%22enabled%22:true,%22type%22:%22sine%22,%22rate%22:99,%22depth%22:0.395},%22bitness%22:%228%22,%22panner%22:0,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:66,%22noMIDIPortsFound%22:true,%22velocity%22:66,%22solidMode%22:true,%22lastNoteOnMode%22:true}}) | [Harsh noise](https://bs.stranno.su/#{%22readingSpeed%22:0.0001,%22waveType%22:%22sine%22,%22gain%22:2.56,%22transitionType%22:%22immediately%22,%22frequencyMode%22:%22continuous%22,%22frequenciesRange%22:{%22from%22:41,%22to%22:90},%22notesRange%22:{%22from%22:48,%22to%22:104},%22fragment%22:{%22from%22:0,%22to%22:100720},%22midiMode%22:false,%22biquadFilterFrequency%22:418.5,%22biquadFilterQ%22:66.6,%22LFO%22:{%22enabled%22:true,%22type%22:%22sine%22,%22rate%22:91,%22depth%22:0.546},%22bitness%22:%228%22,%22panner%22:0.15,%22loop%22:true,%22isRandomTimeGap%22:true,%22midi%22:{%22port%22:null,%22channel%22:0,%22pitch%22:8192,%22modulation%22:66,%22noMIDIPortsFound%22:true,%22velocity%22:66,%22solidMode%22:true,%22lastNoteOnMode%22:true}})
24 | - нажмите на любом месте экрана и загрузите любой файл (файлы никуда не отправляются, всё вычисляется на вашем устройстве)
25 | - нажмите пробел или кнопку Play
26 | - нажмите и удерживайте клавишу `S` и подвигайте мышью. Мышью можно двигать бесконечно. Нажатие `Esc` вернёт курсор
27 | - при зажатой клавише `S` нажмите `Shift` для "усиления" или `Ctrl` для "ослабления" ввода
28 | - проделайте похожие действия с другими настройками через зажатие клавиш `Q`, `W`, `A`, `Z`, `X`, `C`, `V` и т.д. (у полей ввода справа указана соответствующая клавиша)
29 | - откройте параллельно ещё несколько вкладок с инструментом и запустите
30 | - перемещайтесь между вкладками через `Ctrl + номер вкладки` (9 максимум), либо `Ctrl + Tab` / `Ctrl + Shift + Tab`
31 | - обработайте звук налету, подключив педали эффектов, либо с помощью Ableton или других DAW и [Virtual audio cable](https://vac.muzychenko.net/en/)
32 | - переключитесь в MIDI-режим и управляйте виртуальным или внешним синтезатором с помощью [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)
33 | - сохраните настройки просто скопировав URL или через Save settings
34 | - скопируйте инструмент, чтобы играть без интернета, нажав на правую кнопку мыши — Сохранить как, либо скачайте отсюда из папки `/dist`
35 |
36 | ## Содержание
37 |
38 | - [Принцип работы](#principle)
39 | - [Переход в гранулярный режим](#granular)
40 | - [Рекомендации по оптимальной работе](#recommendation)
41 | - [MIDI](#midi)
42 | - [Интерфейс](#interface)
43 | - [Сохранение настроек](#settings)
44 | - [Запуск локально и сборка проекта](#run)
45 |
46 | ## Принцип работы
47 |
48 |
49 | Все данные на любом компьютере или смартфоне представлены в виде файлов (являющихся, по своей сути, текстами). Содержанием этих файлов в конечном итоге являются просто нули и единицы. И эти нули и единицы, в общем-то, все одинаковые, поэтому нам нужен интерпретатор, для того чтобы извлечь смысл из этих текстов. Можно сказать, что формат файла (.mp3, .docx и т.д.) это просто указатель, какому интерпретатору надо передать текст, чтобы из него извлечь смысл.
50 |
51 | Но что, если формат файла и интерпретатор не совпадают?
52 |
53 | Что касается музыкальных экспериментов, то ранее были, например, попытки "воспроизвести" текстовый или иной файл через аудио-редактор.
54 |
55 | Мы могли бы пойти дальше и написать собственный интерпретатор, который смотрел бы на файлы безотносительно формата, использовал собственную "манеру чтения" исходных нулей и единиц и на этой основе предоставлял полноценную систему управляемого синтеза звуков.
56 |
57 | 1. Мы можем интерпретировать файлы как массив чисел. То есть, мы разбиваем непрерывный машинный код на _слова_ некоторой информационной ёмкости (разрядности):
58 |
59 | - 8 бит (числа от 0 до 255)
60 | - 16 бит (числа от 0 до 65 535)
61 |
62 | 2. Тогда, каждое слово есть команда, определяющая частоту звука
63 |
64 | 3. На уровне всей системы мы задаём глобальные параметры:
65 |
66 | - скорость интерпретации
67 | - наличие случайной величины разброса скорости интерпретации
68 | - музыкальный строй (или его отсутствие), диапазон нот/частот; по этому диапазону равномерно сопоставляются частоты по 256 или 65 536 возможным комбинациям нулей и единиц
69 | - зацикленность воспроизведения
70 | - режим MIDI
71 | - плавный или резкий переход между командами
72 | - настройки виртуальных устройств, необходимых для синтеза (осциллятор, фильтр, LFO), либо настройки MIDI
73 |
74 | 4. Чтобы снизить нагрузку на устройство, делим файл на куски по 500 команд
75 |
76 | 5. Рекурсивно планируем управление синтезом, читая по 500 команд в итерации и используя глобальные параметры
77 |
78 | 6. Если дошли до конца файла, прекращаем исполнение, либо начинаем заново
79 |
80 | ## Переход в гранулярный режим
81 |
82 |
83 | > **Note**: Здесь и далее используются термины интерфейса инструмента. Их описание смотрите ниже в разделе Особенности интерфейса
84 |
85 | Гранулярный синтез оперирует мелкими кусочками звуков — акустическими пикселями. Принято считать, что гранулярный синтез "начинается" при оперировании звуками <50мс. При значениях `fragment` * `reading speed` = <50 мы начинаем оперировать уже акустическими пикселями.
86 |
87 | При этом каждую команду из `fragment` можно считать "субпикселем", который, при включённом `random time gap`, каждый раз уникален, а пиксель, соответственно, уникален кратно количеству субпикселей. В итоге мы получаем мутирующий тембр.
88 |
89 | В классическом гранулярном синтезе пиксели играют одновременно и параллельно, и их количество может меняться со временем. В BS же пиксели образуют нить, по которой мы движемся.
90 |
91 | *То есть, если в обычном гранулярном синтезе на слушателя как бы опрокидывают грузовик с песком, где каждая песчинка это акустический пиксель, то здесь этот песок высыпается через воронку диаметром с одну песчинку и вот эту тонкую струю мы и наблюдаем.*
92 |
93 | На изображении ниже показано формирование акустического пикселя из двух команд (`fragment: from = 0, to = 1`), при скорости чтения 0.005 с. Необходимо учитывать, что у каждой частоты есть период *T*, равный отношению единицы времени (1 секунды = 1000 миллисекунд) к частоте. Это значит, что мы можем мыслить звук не только через частоту, но и через время, за которое волна делает одно полное колебание. Если волна не успевает сделать полное колебание, такой объект называется "вейвлетом".
94 |
95 | 
96 |
97 | ## Рекомендации по оптимальной работе
98 |
99 |
100 | - Использовать режим инкогнито при отключённых расширениях
101 | - Браузер не-инкогнито закрыть
102 | - В инкогнито оставить только вкладки с BS
103 | - Использовать отдельный браузер [ungoogled-chromium](https://github.com/ungoogled-software/ungoogled-chromium), потребляющий немного меньше CPU и сильно меньше ОЗУ.
104 |
105 | BS под нагрузкой требует в среднем до 7.1% CPU, в режиме инкогнито 6%, Firefox 4.2%, но работает менее стабильно. Также открытая консоль/DevTools браузера повышает потребление CPU на каждой вкладке на 10%. Рекомендуется использовать BS в режиме инкогнито без любых других открытых вкладок, кроме вкладок BS, для максимальной эффективности.
106 |
107 | Более интересный звук получается при нескольких независимых экземплярах BS в разных вкладках. Теоретически, можно было бы реализовать несколько потоков работы BS в одной вкладке, но это менее оптимально, так как браузеры ограничивают максимальное потребление CPU на вкладку (в Chrome это 10% CPU). Также, у каждой вкладки свой [event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop). Для быстрого переключения между вкладками можно использовать `ctrl + номер вкладки`.
108 |
109 | ## MIDI
110 |
111 |
112 | При включении MIDI-режима автоматически выбирается первый попавшийся порт из доступных и его первый канал. Далее последовательно при чтении посылается сигнал `noteOn`, через время `reading speed` посылается сигнал `noteOff`. В `continuous` режиме после каждого `noteOn` посылается `Pitch` сигнал, чтобы попасть в нужную частоту.
113 |
114 | MIDI-сообщения могут посылаться:
115 |
116 | - в соседние вкладки и окна браузеров, если они слушают MIDI (например, в веб-аналог [DX7](http://mmontag.github.io/dx7-synth-js))
117 | - в DAW и прочие приложения, где есть виртуальные синтезаторы (то есть BS может управлять, например, синтезатором в Ableton)
118 | - во внешние устройства, поддерживающие MIDI и подключённые к компьютеру
119 |
120 | Для передачи MIDI-сообщений в DAW на устройствах Windows можно воспользоваться [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html).
121 |
122 | > **Note**: После любых манипуляций с MIDI-портами (подключение/отключение/переподключение) необходимо полностью перезапустить браузер, закрыв все окна браузера если их несколько
123 |
124 | > **Note**: MIDI-сообщения генерируются только на десктопе
125 |
126 | ## Интерфейс
127 |
128 |
129 | - `Reading speed` — скорость интерпретации; на высоких скоростях более 0.001 приложение может работать нестабильно
130 |
131 | - `Bitness` — мы можем разделить двоичный код на слова по 8 или 16 бит, что меняет количество доступных частот (256 или 65536)
132 |
133 | - `Panner` — панорамирование между левым (-1) и правым (1) каналами
134 |
135 | - `Frequency generation mode`
136 |
137 | - `continuous` — непрерывное распределение частот
138 | - `tempered` — распределение по 12-ступенному равномерно-темперированному строю. Доступны ноты от C-2 до B8
139 |
140 | - `Transition type` — переход между частотами
141 |
142 | - `immediately` — моментально, грубый переход
143 | - `linear` — линейно до следующей частоты
144 | - `exponential` — экспоненциально до следующей частоты
145 |
146 | - `Random time gap` — добавление случайной величины времени до следующего звука в пределах параметра `reading speed`. Делает звук менее "роботизированным", так как расстояние до каждого звука немного отличается и это добавляет больше "живости" игре
147 |
148 | - `Fragment` — позволяет играть не весь файл, а его определённую часть
149 |
150 | - `Sample rate` — частота дискретизации. В большинстве случаев слабо влияет на звук, но очень важен при игре на сверхнизких частотах вроде frequencies range 0 - 1
151 |
152 | - `Solid Mode` — режим "сплошного нажатия", не посылает команды `noteOff`; если подряд идут одинаковые команды (и как следствие ноты), то даже noteOn не посылается. В конце посылается `allSoundOff`. На некоторых синтезаторах позволять осуществить плавные переходы между нотами
153 |
154 | - `Last noteOn mode` — оставляет нажатой последнюю команду в лупе. Позволяет делать более плавные переходы между повторами паттернов.
155 |
156 | - У некоторых полей ввода есть клавиатурное сокращение: при нажатии соответствующей клавиши автоматически наводится фокус на элемент. При зажатии клавиши и одновременном движении мышью можно плавно менять значения. При нажатии Shift можно увеличить (10x, 100x, 1000x) "мощность" изменения значения, при нажатии на Ctrl уменьшить (0.1x, 0.01x, 0.001x). Курсор при этом пропадает, чтобы иметь возможность бесконечно изменять значения. Для возврата курсора необходимо нажать Esc.
157 |
158 | ## Сохранение настроек
159 |
160 |
161 | Сохранить настройки можно двумя путями:
162 |
163 | - через URL-ссылку. При щелчке в адресную строку браузера приложение автоматически формирует ссылку, в которую записываются настройки. Вы можете скопировать её и при открытии ссылки настройки сразу применятся, вам остаётся только загрузить файл для синтеза звука.
164 | - через файл. В интерфейсе преусмотрены кнопки Save / Load / Restore settings, которые позволяют сохранить на компьютер или загрузить из него файл с настройками, а также восстановить исходные.
165 |
166 | ## Запуск локально и сборка проекта
167 |
168 |
169 | ### Просто скопировать приложение
170 |
171 | Всё необходимое для работы системы заложено в единственный `.html` файл, который можно скачать в папке `dist`, либо просто перейти на https://bs.strannо.su и, нажав правую кнопку мыши, в меню выбрать Сохранить как.
172 |
173 | ### Собрать билд локально для доработки кода
174 |
175 | Tech stack: Vue3 + Pinia + Vite.
176 |
177 | 1. Скачать и установить LTS версию Node.js
178 | 2. Скачать код напрямую с Github, либо через `git clone`
179 | 3. В папке с проектом в терминале выполнить:
180 |
181 | ```bash
182 | npm i
183 | npm run dev # development-сборка
184 | npm run build # production-сборка, генерирует index.html со всем необходимым
185 | ```
186 |
187 | Для тестов MIDI можно пользоваться этим ресурсом https://studiocode.dev/midi-monitor/
--------------------------------------------------------------------------------
/src/components/Status.vue:
--------------------------------------------------------------------------------
1 |
175 |
176 |
177 |
178 |
179 |
180 | Playing: {{ status.playing }}
181 |
182 |
183 | Playing time: {{ toHHMMSS(time) }} | {{ time }}
184 |