Форум программистов, компьютерный форум, киберфорум
Программирование звука
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696

Программа-синтезатор

09.02.2020, 11:28. Показов 9900. Ответов 46
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Это программа синтезатор синусоидальных звуков с возможностью добавления гармоник.
Через виртуальный миди-кабель может управляться секвенсером (например, Cubase).
Вывод звука идет с минимальной задержкой через библиотеку ASIO (используется дополнительно bass.dll)

Программа синтезатор позволяет играть на миди-клавиатуре.

Решил выложить исходники на гитхаб.

Кому-то пригодится как пример использования вывода звука через ASIO и вообще генерации звука как такового.

https://github.com/wiz3267/ASIOSynthesizer
Миниатюры
Программа-синтезатор  
3
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.02.2020, 11:28
Ответы с готовыми решениями:

Собственный синтезатор речи
Народ всем привет. Помогите не опытному студенту. В общем написал бота и научил его говорить. Но столкнулся с проблемой, что бот говорит...

Синтезатор
Всем доброго времени суток, хочу сделать простенький синтезатор, путем Beep'а определенной частоты по нажатой клавише, написал кое-что,...

Синтезатор на С++
На ОПИ задали сделать проект, тема любая. Пришла мне в голову такая идея, сделать синтезатор(электро-пианина) на С++(неочень сложный по...

46
Юзер с абсолютным слухом
 Аватар для Опан
709 / 489 / 195
Регистрация: 17.12.2010
Сообщений: 1,428
12.04.2020, 17:01
Студворк — интернет-сервис помощи студентам
Из последнего архива Ваша программа не открывается, появляется пустое окно и сообщение системы, что эта программа перестала работать. Предыдущая верся работает.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
15.04.2020, 09:36  [ТС]
Опан, здравствуйте! Я обновил репозиторий, можно попробовать еще раз скачать и запустить. Ваши проекты я также посмотрел. Оба работают.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
15.04.2020, 12:09  [ТС]
Окно выглядит сейчас так:
0
Юзер с абсолютным слухом
 Аватар для Опан
709 / 489 / 195
Регистрация: 17.12.2010
Сообщений: 1,428
19.04.2020, 16:59
Здравствуйте! В Вашей программе у меня не воспроисводится записанная мелодия. Как включить воспроизведение аккорда одной клавишей? Не получается издать длительный звук с помощью длительного нажатия мыши, при этом 2-3 раза повторяется короткий звук. После нажатия на кнопку ASIO Control Panel программа зависает. Спасибо, что посмотрели мои программы.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
19.04.2020, 18:28  [ТС]
Здравствуйте! Для воспроизведения аккорда одной клавишей надо поднять три гармоники как на картинке, это будет соответствовать мажорному аккорду.


Для издания длительного звука от мышки нужно установить флажок "Piano mouse click".
Насчет того, что записанная мелодия не воспроизводится - пока мелодия не записывается при нажатии мыши, может в этом дело. С миди и с обычной клавиатуры запись должна идти. Для лучшей поддержки ASIO можно установить драйвера ASIO4ALL
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
20.04.2020, 11:39  [ТС]
Опан, Вы молодец, программа хорошая у Вас. Вот жаль только продолжения нет. (Или есть? Судя по справке, проект был написан в 2008 году)


С выбором разных стилей для автоаккомпанимента + поддержка MIDI-клавиатуры.

Вы не хотите также сделать проект доступным на GitHub? Также могу предложить присоединится к нам по теме моего синтезатора, сейчас кроме меня есть еще один разработчик.
0
Юзер с абсолютным слухом
 Аватар для Опан
709 / 489 / 195
Регистрация: 17.12.2010
Сообщений: 1,428
21.04.2020, 16:29
К сожалению, исходник утерян, но будет время, хочу её восстановить с нуля. Как продолжение, я хотел реализовать подключение миди-клавиатуры, и долго откладывал, пока не затерял исходник. О GitHub тоже думал. Присоединиться согласен.

Добавлено через 5 часов 0 минут
Вот ещё начал разрабатывать синтезатор с веб-интерфейсом. (HTML + Javascript + технология Webaudio Api) Веб-интерфейс даёт возможность играть прямо на сайте, ничего не скачивая: Веб-синтезатор В отличии от второго моего вложения, настройки можно менять мгновенно. (тоже случайным образом одним нажатием)
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
28.05.2020, 13:14  [ТС]
Проект понемногу развивается, новый интерфейс, можно генерировать отдельно пилу, прямоугольный и синус сигнал и их смешивать вместе. добавлена опция записи в RAW файл звука и отключения фильтра для пилообразного сигнала. значения для гармоник 5 и 6 записываются и в настройки. добавлены функции для чтения и записи в ini-файл double значений. Благодарю пользователя Опан за помощь.



Проект скачать можно здесь:
https://github.com/wiz3267/ASIOSynthesizer
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
09.07.2020, 19:04  [ТС]
Программа понемногу развивается, добавлено эхо, выбор сложной волны, состоящей из отдельных гармоник, частотная модуляция и др. функции.
Адрес загрузки тот же.
1
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
16.08.2023, 09:03  [ТС]
Хотел спросить, пригодился ли кому-то этот цифровой продукт? Допиливал ли кто его, использовал ли для создания музыки?
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
23.08.2024, 16:56  [ТС]
C огромной любовью я хотел бы выразить вам благодарность за поддержку темы.

Я же, решив не ждать ещё долгие годы, решил возобновить, всё-таки, работу над синтезатором.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
13.11.2025, 09:32  [ТС]
Сейчас морда лица синтезатора выглядит так:
Миниатюры
Программа-синтезатор  
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6813 / 2053 / 238
Регистрация: 14.12.2014
Сообщений: 4,313
Записей в блоге: 12
14.11.2025, 12:11
zorxor,
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
09.12.2025, 16:57  [ТС]
Jin X, я знаю о проблеме, это на Windows 10. Почему так - чтобы разобраться, мне нужно поставить Visual Studio 6.0, чтобы поймать ошибку в отладчике. Я даже не знаю, а будет ли работать всё это на 10-ке.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
19.12.2025, 11:04  [ТС]
Jin X, здравствуйте! Visual C++ 6.0 поставить не удалось нормально, среда не работает, однако эта ошибка связана с неправильным значением переменной ASIOIndex в конфигурационном файле MidiInPiano.ini, находящемся в подкатологе Presets. Можно попробовать задать ASIOIndex=0. Программа работает на Windows 10.
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6813 / 2053 / 238
Регистрация: 14.12.2014
Сообщений: 4,313
Записей в блоге: 12
19.12.2025, 14:12
zorxor, прога запустилась, но потом вылез системный отладчик с ошибкой Access Violation.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
20.12.2025, 09:45  [ТС]
Jin X, доброе утро, если можно, приведите более подробную информацию, ассемблерный листинг, адрес инструкции, которая вызвала это исключение, чтоб я мог понять, где именно в исходнике находится эта ошибка.

Добавлено через 48 минут
Также прошу правильно меня понять - с ростом проекта увеличивается его сложность, и, даже я, как автор основной идеи, оказываюсь уже неспособным далее развивать проект. Участник форума XLAT, например, говорил мне по поводу исходного кода игры "Солдат Мариа" ("Soldir of Mario"), что у меня отсутствует проектирование - это абсолютно так, я пишу как бы по наитию, свыше. Но...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/////////////////////////////////////////////////////////////////////////////
// CDTFM_GeneratorDlg dialog
 
CDTFM_GeneratorDlg::CDTFM_GeneratorDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CDTFM_GeneratorDlg::IDD, pParent)
{
 
    //{{AFX_DATA_INIT(CDTFM_GeneratorDlg)
    m_edit = _T("");
    m_midi_open_str = _T("3");
    m_amplitude = _T("32767");
    m_edit_freq = 0.0;
    m_midi_name = _T("");
    m_slider_decrement_double = 0.0;
    m_wave_len = 0.0;
    m_edit_modilation = _T("1");
    m_asio_device = -1;
    m_edit_scale = _T("12");
    m_string_base_a = _T("440");
    m_modulation_amplitude = _T("10000");
    m_string_status_text = _T("");
    m_size_asio_buffer = 0;
    m_garmonic_5 = _T("1.25992");
    m_garmonic_6 = _T("1.49830");
    m_attack = _T("5");
    m_edit_modulation_wheel = _T("");
    m_use_velocity = TRUE;
    m_no_sustain = FALSE;
    m_piano_mouse_click = TRUE;
    m_ctrl_key_use = FALSE;
    m_check_saw3 = FALSE;
    m_sample_rate = 0;
    m_rez_min = _T("-0.5");
    m_rez_max = _T("4");
    m_check_filter2 = FALSE;
    m_garmonic_mode = FALSE;
    m_garmonic_base_freq = _T("50");
    m_write_wav = FALSE;
    m_check_filter1 = FALSE;
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
 
 
void CDTFM_GeneratorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CDTFM_GeneratorDlg)
    DDX_Control(pDX, IDC_LIST_PRESET, m_list_preset);
    DDX_Control(pDX, IDC_STATIC_SIN_SAW_MODE, m_static_sin_saw_mode);
    DDX_Control(pDX, IDC_STATIC_CSLIDER10, m_static_slider10);
    DDX_Control(pDX, IDC_STATIC_CSLIDER9, m_static_slider9);
    DDX_Control(pDX, IDC_EDIT_GLOBAL_FILTER2, m_global_filter2);
    DDX_Control(pDX, IDC_EDIT_GLOBAL_SS, m_global_ss2);
    DDX_Control(pDX, IDC_EDIT_GLOBAL_REZ2, m_global_rez2);
    DDX_Control(pDX, IDC_STATIC_CSLIDER8, m_static_slider8);
    DDX_Control(pDX, IDC_STATIC_CSLIDER7, m_static_slider7);
    DDX_Control(pDX, IDC_STATIC_CSLIDER6, m_static_slider6);
    DDX_Control(pDX, IDC_EDIT_FILL_BUFFER_TICKCOUNT, m_tick_count_fill_buffer);
    DDX_Control(pDX, IDC_STATIC_CSLIDER5, m_static_slider5);
    DDX_Control(pDX, IDC_STATIC_CSLIDER4, m_static_slider4);
    DDX_Control(pDX, IDC_STATIC_CSLIDER3, m_static_sslider3);
    DDX_Control(pDX, IDC_STATIC_CSLIDER2, m_static_slider2);
    DDX_Control(pDX, IDC_STATIC_CSLIDER1, m_static_slider1);
    DDX_Control(pDX, IDC_LEVEL_CONTROL, m_level_control);
    DDX_Control(pDX, IDC_EDIT_PIANOROLL, m_pianoroll);
    DDX_Control(pDX, IDC_SLIDER_TOTAL_VOLUME, m_slider_total_volume);
    DDX_Control(pDX, IDC_EDIT_BASE_A, m_edit_base_a);
    DDX_Control(pDX, IDC_EDIT_STATUS_TEXT, m_status_text);
    DDX_Control(pDX, IDC_AMPLITUDE, m_amplitude_edit);
    DDX_Control(pDX, IDC_SLIDERM6, m_slm6);
    DDX_Control(pDX, IDC_SLIDERM5, m_slm5);
    DDX_Control(pDX, IDC_SLIDER6, m_sl6);
    DDX_Control(pDX, IDC_SLIDER5, m_sl5);
    DDX_Control(pDX, IDC_SLIDER_DECREMENT, m_slider_decrement);
    DDX_Control(pDX, IDC_EDIT_MIDI_NAME2, m_midi_name_ctrl);
    DDX_Control(pDX, IDC_STOP_PLAY, m_stop_play);
    DDX_Control(pDX, IDC_BUTTON_PLAY_WRITEN, m_play_writen);
    DDX_Control(pDX, IDC_BUTTON_WRITE_STOP, m_button_write_stop);
    DDX_Control(pDX, IDC_BUTTON_WRITE, m_button_write);
    DDX_Control(pDX, IDC_BUTTON_MIDI_OPEN, m_midi_open);
    DDX_Control(pDX, IDC_BUTTON_MIDI_CLOSE, m_midi_close);
    DDX_Control(pDX, IDC_SLIDERM4, m_slm4);
    DDX_Control(pDX, IDC_SLIDERM3, m_slm3);
    DDX_Control(pDX, IDC_SLIDERM2, m_slm2);
    DDX_Control(pDX, IDC_SLIDER4, m_sl4);
    DDX_Control(pDX, IDC_SLIDER3, m_sl3);
    DDX_Control(pDX, IDC_SLIDER2, m_sl2);
    DDX_Control(pDX, IDC_SLIDER1, m_sl1);
    DDX_Text(pDX, IDC_EDIT1, m_edit);
    DDX_Text(pDX, IDC_EDIT_MIDI_OPEN, m_midi_open_str);
    DDX_Text(pDX, IDC_AMPLITUDE, m_amplitude);
    DDX_Text(pDX, IDC_EDIT_FREQ, m_edit_freq);
    DDX_Text(pDX, IDC_EDIT_MIDI_NAME2, m_midi_name);
    DDX_Text(pDX, IDC_EDIT_SLIDER_DECREMENT, m_slider_decrement_double);
    DDX_Text(pDX, IDC_EDIT_WAVE_LEN, m_wave_len);
    DDX_Text(pDX, IDC_EDIT_MODULATION, m_edit_modilation);
    DDX_Text(pDX, IDC_EDIT_ASIO_DEVICE, m_asio_device);
    DDX_Text(pDX, IDC_EDIT_SCALE, m_edit_scale);
    DDX_Text(pDX, IDC_EDIT_BASE_A, m_string_base_a);
    DDX_Text(pDX, IDC_EDIT_MODULATION_FREQ, m_modulation_amplitude);
    DDX_Text(pDX, IDC_EDIT_STATUS_TEXT, m_string_status_text);
    DDX_Text(pDX, IDC_EDIT_SIZE_ASIO_BUFFER, m_size_asio_buffer);
    DDX_Text(pDX, IDC_EDIT_GARMONIC_5, m_garmonic_5);
    DDX_Text(pDX, IDC_EDIT_GARMONIC_6, m_garmonic_6);
    DDX_Text(pDX, IDC_EDIT_MODULATION_WHEEL, m_edit_modulation_wheel);
    DDX_Check(pDX, IDC_CHECK_USE_VELOCITY, m_use_velocity);
    DDX_Check(pDX, IDC_CHECK_NO_SUSTAIN, m_no_sustain);
    DDX_Check(pDX, IDC_CHECK_PIANO_MOUSE_CLICK, m_piano_mouse_click);
    DDX_Check(pDX, IDC_CHECK_CTRL_KEY, m_ctrl_key_use);
    DDX_Check(pDX, IDC_CHECK_SAW, m_check_saw3);
    DDX_Text(pDX, IDC_EDIT_SAMPLE_RATE, m_sample_rate);
    DDX_Text(pDX, IDC_EDIT_REZ_MIN, m_rez_min);
    DDX_Text(pDX, IDC_EDIT_REZ_MAX, m_rez_max);
    DDX_Check(pDX, IDC_CHECK_FILTER2, m_check_filter2);
    DDX_Check(pDX, IDC_CHECK_GARMONIC_MODE, m_garmonic_mode);
    DDX_Text(pDX, IDC_EDIT_GARMONIC_BASE_FREQ, m_garmonic_base_freq);
    DDX_Check(pDX, IDC_CHECK_WRITE_WAVDATA, m_write_wav);
    DDX_Check(pDX, IDC_CHECK_FILTER1, m_check_filter1);
    //}}AFX_DATA_MAP
}
 
BEGIN_MESSAGE_MAP(CDTFM_GeneratorDlg, CDialog)
    //{{AFX_MSG_MAP(CDTFM_GeneratorDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_CLOSE()
    ON_WM_CREATE()
    ON_WM_TIMER()
    ON_BN_CLICKED(IDC_BUTTON_MIDI_CLOSE, OnButtonMidiClose)
    ON_BN_CLICKED(IDC_BUTTON_MIDI_OPEN, OnButtonMidiOpen)
    ON_BN_CLICKED(IDC_BUTTON_WRITE, OnButtonWrite)
    ON_BN_CLICKED(IDC_BUTTON_WRITE_STOP, OnButtonWriteStop)
    ON_BN_CLICKED(IDC_BUTTON_PLAY_WRITEN, OnButtonPlayWriten)
    ON_BN_CLICKED(IDC_BUTTON_RESET, OnButtonReset)
    ON_WM_MOVE()
    ON_BN_CLICKED(IDC_STOP_PLAY, OnStopPlay)
    ON_WM_LBUTTONDOWN()
    ON_WM_MOUSEMOVE()
    ON_EN_SETFOCUS(IDC_EDIT_MODULATION, OnSetfocusEditModulation)
    ON_EN_KILLFOCUS(IDC_EDIT_STATUS_TEXT, OnKillfocusEditStatusText)
    ON_EN_KILLFOCUS(IDC_EDIT_MODULATION, OnKillfocusEditModulation)
    ON_EN_SETFOCUS(IDC_EDIT_SCALE, OnSetfocusEditScale)
    ON_EN_KILLFOCUS(IDC_EDIT_SCALE, OnKillfocusEditScale)
    ON_BN_CLICKED(IDC_BUTTON_ASIO_CONTROL_PANEL, OnButtonAsioControlPanel)
    ON_WM_LBUTTONUP()
    ON_WM_RBUTTONUP()
    ON_COMMAND(ID_SETTINGS_SETASIODEVICE, OnSettingsSetasiodevice)
    ON_COMMAND(ID_FILE_EXIT, OnFileExit)
    ON_BN_CLICKED(IDC_BUTTON_DEMO, OnButtonDemo)
    ON_COMMAND(ID_KEYBOARD_KEYS_MENU, OnKeyboardKeysMenu)
    ON_BN_CLICKED(IDC_BUTTON_RND_GARMONIC, OnButtonRndGarmonic)
    ON_BN_CLICKED(IDC_BUTTON_PLUS_XSCALE_WAVEGRAPHIC, OnButtonPlusXscaleWavegraphic)
    ON_BN_CLICKED(IDC_BUTTON_MINUS_XSCALE_WAVEGRAPHIC, OnButtonMinusXscaleWavegraphic)
    ON_BN_CLICKED(IDC_CHECK_GARMONIC_MODE, OnCheckGarmonicMode)
    ON_BN_CLICKED(IDC_CHECK_WRITE_WAVDATA, OnCheckWriteWavdata)
    ON_BN_CLICKED(IDC_CHECK_SAW, OnCheckSaw)
    ON_COMMAND(ID_SETTINGS_LOADPRESETS, OnSettingsLoadpresets)
    ON_COMMAND(ID_SETTINGS_SAVEPRESETS, OnSettingsSavepresets)
    ON_LBN_SELCHANGE(IDC_LIST_PRESET, OnSelchangeListPreset)
    ON_LBN_DBLCLK(IDC_LIST_PRESET, OnDblclkListPreset)
    ON_BN_CLICKED(IDC_BUTTON_SAVE_PRESET, OnButtonSavePreset)
    ON_BN_CLICKED(IDC_BUTTON_LOAD_PRESET, OnButtonLoadPreset)
    ON_WM_LBUTTONDBLCLK()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CDTFM_GeneratorDlg message handlers
int 
    SAMPLE_RATE=44100;
    //SAMPLE_RATE=44100*2;
    //SAMPLE_RATE=48000;
 
CFile filewav, file;
int badopenwav=0;
 
// Структура, описывающая заголовок WAV файла.
struct WAVHEADER
{
    WAVHEADER()
    {
        chunkId[0]='R';
        chunkId[1]='I';
        chunkId[2]='F';
        chunkId[3]='F';
 
        format[0]='W';
        format[1]='A';
        format[2]='V';
        format[3]='E';
 
        subchunk1Id[0]='f';
        subchunk1Id[1]='m';
        subchunk1Id[2]='t';
        subchunk1Id[3]=' ';
 
        subchunk1Size=16;
        audioFormat=1; //PCM
        numChannels=2;  //STEREO
        sampleRate=SAMPLE_RATE;
        bitsPerSample=16;
 
        byteRate=sampleRate * numChannels * bitsPerSample/8;
 
        blockAlign=numChannels * bitsPerSample/8;
 
        subchunk2Id[0]='d';
        subchunk2Id[1]='a';
        subchunk2Id[2]='t';
        subchunk2Id[3]='a';
    }
    // WAV-формат начинается с RIFF-заголовка:
 
    // Содержит символы "RIFF" в ASCII кодировке
    // (0x52494646 в big-endian представлении)
    char chunkId[4];
 
    // 36 + subchunk2Size, или более точно:
    // 4 + (8 + subchunk1Size) + (8 + subchunk2Size)
    // Это оставшийся размер цепочки, начиная с этой позиции.
    // Иначе говоря, это размер файла - 8, то есть,
    // исключены поля chunkId и chunkSize.
    unsigned long chunkSize;
 
    // Содержит символы "WAVE"
    // (0x57415645 в big-endian представлении)
    char format[4];
 
    // Формат "WAVE" состоит из двух подцепочек: "fmt " и "data":
    // Подцепочка "fmt " описывает формат звуковых данных:
    
    // Содержит символы "fmt "
    // (0x666d7420 в big-endian представлении)
    char subchunk1Id[4];
 
    // 16 для формата PCM.
    // Это оставшийся размер подцепочки, начиная с этой позиции.
    unsigned long subchunk1Size;
 
    // Аудио формат, полный список можно получить здесь http://audiocoding.ru/wav_formats.txt
    // Для PCM = 1 (то есть, Линейное квантование).
    // Значения, отличающиеся от 1, обозначают некоторый формат сжатия.
    unsigned short audioFormat;
 
    // Количество каналов. Моно = 1, Стерео = 2 и т.д.
    unsigned short numChannels;
 
    // Частота дискретизации. 8000 Гц, 44100 Гц и т.д.
    unsigned long sampleRate;
 
    // sampleRate * numChannels * bitsPerSample/8
    unsigned long byteRate;
 
    // numChannels * bitsPerSample/8
    // Количество байт для одного сэмпла, включая все каналы.
    unsigned short blockAlign;
 
    // Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д.
    unsigned short bitsPerSample;
 
    // Подцепочка "data" содержит аудио-данные и их размер.
 
    // Содержит символы "data"
    // (0x64617461 в big-endian представлении)
    char subchunk2Id[4];
 
    // numSamples * numChannels * bitsPerSample/8
    // Количество байт в области данных.
    unsigned long subchunk2Size;
 
    // Далее следуют непосредственно Wav данные.
} Wavheader ;
 
double global_fRez2;
double global_ss2;
double global_filter2;
int GarmonicBaseFreq;
 
 
double camerton = 110.0;
double fadeOut = 1.00004; // От этого зависит время затухания клавиш пианино.
//double piano_detune = 1.005; // Погрешность настройки струн пианино. Для озвучки фильмов Чарли Чаплина лучше ставить побольше.
//double piano_detune = 1.002; // Погрешность настройки струн пианино. Для озвучки фильмов Чарли Чаплина лучше ставить побольше.
double piano_detune = 1.000;
 
DWORD FillBufferTickCount=0;
 
int counter = 0;
int demo[] = {50,-1,-1,-1,53,-1,-1,50,-1,50,55,-1,50,-1,48,-1,50,-1,-1,-1,57,-1,-1,50,-1,50,58,-1,57,-1,53,-1,50,-1,57,-1,62,-1,50,48,-1,48,45,-1,52,-1,50};
 
CPoint g_last_mouse_point;
CDTFM_GeneratorDlg * g_mainwindow=NULL;
 
BOOL no_sustain;
double garmonic_5=0;
double garmonic_6=0;
double ADSR_Attack=0;
 
//double globalVolume=0.5;
 
CircleSliderIndicator * cCircleSlider_attack=NULL;
CircleSliderIndicator * cCircleSlider_modulation=NULL;
CircleSliderIndicator * cCircleSlider_detune=NULL;
CircleSliderIndicator * cCircleSlider_filterspeed=NULL;
CircleSliderIndicator * cCircleSlider_filterspeed2=NULL;
CircleSliderIndicator * cCircleSlider_6=NULL;
CircleSliderIndicator * cCircleSlider_7=NULL;
CircleSliderIndicator * cCircleSlider_sqr=NULL;
 
CircleSliderIndicator * cCircleSlider_echo_time=NULL;   //время эха
CircleSliderIndicator * cCircleSlider_echo_decay=NULL;  //затухание эха
//CircleSliderIndicator * cCircleSlider_detune=NULL;
 
int global_asio_index=0;
 
const double PI=3.1415926;
 
int NeedUpdateMidiEvent=1;  //обновлять Midi сообщения
int NeedUpdateBaseFreq=0;   //менять базовую частоту при изменения слайдера
 
int NeedUpdateModulation=1; ////***^^^*** реагировать на слайдер модуляции 
double g_modulation_t=0;    //***^^^***
double g_step_modulation=0; ////***^^^*** скорость модуляции 
double g_ModulationWheel=0; //***^^^***
int g_modulation_wheel_2=0; ////***^^^***значения колеса модуляции
int g_modulation_amplitude_value;//***^^^***
 
CString g_edit_list_midi;
 
double scale;//=pow(2.0,1.0/12.0);
 
CString g_amplitude_global="";
 
void MidiKeyPress2(BYTE key, BYTE value);
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
 
CINIFiles ini;
 
void SetKeys(int n, int vol);
 
int BaseKeyboard=59;
double BASE_A;
 
int change=true;
 
HMIDIIN hmidiIn;
 
CString ENDL="\r\n";
 
//CFile file;
 
BYTE *PlayWriten=NULL;
DWORD PlayWritenSize=0;
WORD PlayWritenPosition=0;
 
bool write=false; //нужно ли записывать в файл
 
int CurrentAmplitude=0;
 
int Overload=-100; //перегрузка звуков. уровня >32767 OR <-32767
 
union DWORD_BYTES
{
    DWORD data;
    BYTE b[4];
};
 
struct MIDI_DATA
{
    BYTE key;
    BYTE status;
    BYTE reserv1,reserv2;
    DWORD time;
};
 
double MaxSound=0;  //максимальный уровень звука на данный момент (до 32768)
 
 
//получить данные из формы в переменные
#define GetData UpdateData(true)
 
//положить (обновить) данные из переменных в форму
#define PutData UpdateData(false)
 
static int _time_;
 
double  AMPLITUDE_DECREMENT;//5/2048.0;
 
int IdMidiOpen=-1;
Вот, ниже, представлена критическая с точки зрения использования ресурсов процессора функция, условно названная Piano - так как она используется для каждого сэмпла генерируемого звука. Что я делаю не так? Нужно переписывать функцию на asm или ещё что.
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
20.12.2025, 10:31  [ТС]
Что касается самой критической с точки зрения производительности функции Piano(...).
Во-первых, часть функции делал участник форума Опан, как это работает - я понятия не имею.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
//функция Piano используется для генерации звука
 
//сигнал в соответствии с эквалайзером в графическом интерфейсе программы
//Ampl амплитуда
//freq базовая частота сигнала
//flag_one число используемых и вычисленных гармоник
 
//freq_actual записывается последняя вычисленная частота
//если flag_one==1, значит была использована только одна гармоника,
//а остальные слайдеры опущены вниз
double Piano(int keyN,double Ampl, double freq, double t, double phase, int & flag_one, double & freq_actual)
{
    double static tmp1,tmp2;
 
    flag_one=0;
 
    //if (sl1 && !g_mainwindow->m_check_saw3) {flag_one++;freq_actual=freq;}    //base frequency
    if (sl1) {flag_one++;freq_actual=freq;} //base frequency
    //if (sl2) {flag_one++;freq_actual=freq*2;}
    if (sl2) {flag_one++;freq_actual=freq;}
    
    //if (sl3) {flag_one++;freq_actual=freq*3;}
    if (sl3) {flag_one++;freq_actual=freq;}
 
    if (sl4) {flag_one++;freq_actual=freq;}
    
    //if (sl5) {flag_one++;freq_actual=freq*5;}
    if (sl5) {flag_one++;freq_actual=freq*garmonic_5;}
    
    //if (sl6) {flag_one++;freq_actual=freq*6;}
    if (sl6) {flag_one++; freq_actual=freq*garmonic_6;}
 
    if (slm2) {flag_one++;freq_actual=freq/2;}
    if (slm3) {flag_one++;freq_actual=freq/3;}
    if (slm4) {flag_one++;freq_actual=freq/4;}
    if (slm5) {flag_one++;freq_actual=freq/5;}
    if (slm6) {flag_one++;freq_actual=freq/6;}
 
    double k=0; //итоговая вычисленная сумма 
 
    double limit=20500; //ограничение частоты
 
    //амплитуда сигнала
    double AMP=Ampl;
 
    //***^^^*** связано с амплитудной модуляцией
    AMP+=
        g_modulation_amplitude_value//глубина модуляции
        *sin(g_modulation_t);
 
    double f;   //частота отдельной синусоиды
    //freq базовая синусоида
 
    //если поднят первый слайдер (базовая гармоника)
    if (sl1) {
 
        if (g_mainwindow->m_check_saw3)
        {
            double dt=1 + cCircleSlider_detune->GetValue()/5000.0;
            //double dt=1 + 1.0/pow(2, cCircleSlider_detune->GetValue()/10.0);
 
 
            double myconst = (myMax - myMin) / SAMPLE_RATE;
 
            //Keys[keyN].sawSource1 += freq * 0.000032 * dt;
            //Keys[keyN].sawSource2 += freq * 0.000032 / dt;
            
            //Keys[keyN].sawSource1 += freq * myconst * dt;
            //Keys[keyN].sawSource2 += freq * myconst / dt;
 
            //int fmodulation_f = 50; // частота частотной модуляции
            //int fmodulation_d = 50; // глубина частотной модуляции
 
            double fmodulation_f = cCircleSlider_6->GetValue(); // частота частотной модуляции
            double fmodulation_d = cCircleSlider_7->GetValue(); // глубина частотной модуляции
 
            double fmodulation = 1 + (1 - pow(1.001, fmodulation_d)) * sin(t * pow(1.015, fmodulation_f));
            
            Keys[keyN].sawSource1 += freq * myconst * dt * fmodulation;
            Keys[keyN].sawSource2 += freq * myconst / dt * fmodulation;
            
            //Keys[keyN].sawSource1 += freq * myconst * dt;
            //Keys[keyN].sawSource2 += freq * myconst / dt;
 
            //8jul2020
            //if(Keys[keyN].sawSource1 >= myMax) Keys[keyN].sawSource1 = myMin - myMax + Keys[keyN].sawSource1;
            //if(Keys[keyN].sawSource2 >= myMax) Keys[keyN].sawSource2 = myMin - myMax + Keys[keyN].sawSource2;
            
            if(Keys[keyN].sawSource1 >= myMax){
                tmp1 = Keys[keyN].sawSource1 - myMax;
                Keys[keyN].sawSource1 = myMin;
            }
            if(Keys[keyN].sawSource2 >= myMax){
                tmp2 = Keys[keyN].sawSource2 - myMax;
                Keys[keyN].sawSource2 = myMin;
            }
 
            
            //if(Keys[keyN].sawSource1 >= myMax) Keys[keyN].sawSource1 = myMin;
            //if(Keys[keyN].sawSource2 >= myMax) Keys[keyN].sawSource2 = myMin;
            
            double sawSource = Keys[keyN].sawSource1 + Keys[keyN].sawSource2+ tmp1 + tmp2;
 
            if (g_mainwindow->m_check_filter1 == 0)
            {
                Keys[keyN].filter1=sawSource;
            }
 
            else
            {
                filterSpeed = //500 * (cCircleSlider_filterspeed->GetValue()+1);
 
                //pow(2, 9 + cCircleSlider_filterspeed -> GetValue() / 15.0);
                pow(2, 9 + cCircleSlider_filterspeed -> GetValue() / 10.0);
 
                Keys[keyN].fRez1 -= (Keys[keyN].fRez1 - rezMin) / filterSpeed;
                //Keys[keyN].ss1 += (sawSource - Keys[keyN].filter1) / pow(2, rezMax - Keys[keyN].fRez1 + 4);
                Keys[keyN].ss1 += (sawSource - Keys[keyN].filter1) / pow(4, 6 - Keys[keyN].fRez1);
 
                //Keys[keyN].ss1 /= 1.02;
                Keys[keyN].ss1 /= 1.01;
                Keys[keyN].filter1 += Keys[keyN].ss1;
            }
                
                        
            k += Keys[keyN].filter1 * sl1/100.0; // базовый звук
            
    
            //k *= sl1 / 100.0;
        }
        else
        {
            f=freq; 
            
            if (f<limit) k+=sl1/100.0*sin(f*t);
        }
        
    }
 
    //если поднят второй слайдер 
    if (sl2) 
    {
        //f=2*freq; 
        
        f=freq; 
        //floor
        //double val=floor(sin(f*t)+0.1);
        double val=sin(f*t);
        double fix=cCircleSlider_sqr->GetValue()/100.0;
        //double fix=0;
 
        if (val>=fix) val=1;
        if (val<-fix) val=-1;
        
 
        if (f<limit) k+=sl2/100.0*val; 
    }
 
    if (sl3) 
    {
        
        ///f=3*freq; 
        ////if (f<limit) k+=sl3/100.0*sin(f*t); 
 
        bool randgarmony = true; // разрешение выполнять функцию ниже
        if(randgarmony == true)
        {
 
            //double out = 0.4 * sin(freq * t); //base freq
            double out = 0;
 
            for(int i = 0; i < garm_c; i ++) 
            {
                //out += 0.1/(i+1) * sin(freq * randarray[i] * t);
                if (randarray[i])
                {
                    double f=freq * i;
                    if (f<limit)
                    {
                        out += randarray_amplitude[i] * sin(f*t);
                    }
                }
            }
 
             // дальше уже знакомый код фильтра, только на вход подаём переменную out
            filterSpeed = pow(2, 9 + cCircleSlider_filterspeed -> GetValue() / 10.0);
            
            Keys[keyN].fRez2 -= (Keys[keyN].fRez2 - rezMin) / filterSpeed;
        
            /*if ( (Keys[keyN].fRez2-rezMin)<0.5)
            {
                Keys[keyN].ResetFilter();
            }*/
 
            
            Keys[keyN].ss2 += (out - Keys[keyN].filter2) / pow(4, 6 - Keys[keyN].fRez2);
            //Keys[keyN].ss1 /= 1.02;
            Keys[keyN].ss2 /= 1.01 ;
            Keys[keyN].filter2 += Keys[keyN].ss2;
 
            global_fRez2=Keys[keyN].fRez2;
            global_ss2=Keys[keyN].ss2;
            global_filter2=Keys[keyN].filter2;
 
 
            double filterSpeed3 = pow(2, 9 + cCircleSlider_filterspeed2 -> GetValue() / 10.0);
            
            Keys[keyN].fRez3 -= (Keys[keyN].fRez3 - rezMin) / filterSpeed3;
            Keys[keyN].ss3 += (out - Keys[keyN].filter3) / pow(4, 6 - Keys[keyN].fRez3);
            Keys[keyN].ss3 /= 1.01 ;
            Keys[keyN].filter3 += Keys[keyN].ss3;
 
 
            
            int filter_on=g_mainwindow->m_check_filter2;
            if (filter_on)
            {
                //k += Keys[keyN].filter2 * sl3 * 0.01; // добавляем результат в общий поток
                k += 0.5*(Keys[keyN].filter2 + Keys[keyN].filter3)* sl3 * 0.01; // добавляем результат в общий поток
            }
            else
            {
                k += out * sl3 * 0.01;
            }
 
        }
 
    
    
    }
 
    //if (sl4) { f=4*freq; if (f<limit) k+=sl4/100.0*sin(f*t); }
    if (sl4) {
 
        double str1 = pow(piano_detune, Keys[keyN].pianostr1);
        double str2 = pow(piano_detune, Keys[keyN].pianostr2);
        double str3 = pow(piano_detune, Keys[keyN].pianostr3);
    
        double freq1 = freq / 64;
        
        if(sin(Keys[keyN].frameCount / camerton * freq1) * Keys[keyN].polarity < 0){
        
            Keys[keyN].polarity = -Keys[keyN].polarity;
            Keys[keyN].resonance = 1.0;
            
        }
        
        Keys[keyN].pianoamp /= fadeOut;
        Keys[keyN].resonance /= 1.01;
        
        double fm = 50.0 * sin( Keys[keyN].frameCount / camerton * freq1 * floor(12 / freq1)) * Keys[keyN].resonance;
        
        double fm1 = 50.0 * sin( Keys[keyN].frameCount / camerton * freq1 * floor(12 / freq1) * str1) * Keys[keyN].resonance;
        double fm2 = 50.0 * sin( Keys[keyN].frameCount / camerton * freq1 * floor(12 / freq1) * str2) * Keys[keyN].resonance;
        double fm3 = 50.0 * sin( Keys[keyN].frameCount / camerton * freq1 * floor(12 / freq1) * str3) * Keys[keyN].resonance;
        
        double garmony = (Keys[keyN].frameCount + fm1) / camerton * freq1;
        double k1 = Keys[keyN].pianoamp * (sin(garmony) + sin(garmony * 2.0));
        
        garmony = (Keys[keyN].frameCount + fm2) / camerton * freq1;
        k1 += Keys[keyN].pianoamp * (sin(garmony) + sin(garmony * 2.0));
        
        garmony = (Keys[keyN].frameCount + fm3) / camerton * freq1;
        k1 += Keys[keyN].pianoamp * (sin(garmony) + sin(garmony * 2.0));
        
        k += k1 * sl4 / 100;
        
        Keys[keyN].frameCount ++;
 
    }
    
    //if (sl5) { f=5*freq; if (f<limit) k+=sl5/100.0*sin(f*t); }
    if (sl5) { f=garmonic_5*freq; if (f<limit) k+=sl5/100.0*sin(f*t); }
 
    //if (sl6) { f=6*freq; if (f<limit) k+=sl6/100.0*sin(f*t); }
    if (sl6) { f=garmonic_6*freq; if (f<limit) k+=sl6/100.0*sin(f*t); }
 
 
    //в два и более раза меньшие гармоники
    if(slm2) k+=slm2/100.0*sin(freq/2*t);
    if(slm3) k+=slm3/100.0*sin(freq/3*t);
    if(slm4) k+=slm4/100.0*sin(freq/4*t);
    if(slm5) k+=slm5/100.0*sin(freq/5*t);
    if(slm6) k+=slm6/100.0*sin(freq/6*t);
 
    //***^^^*** свяазано с модуляцией
    if (g_modulation_amplitude_value)
    {
        return k *  (slvolume/100.0) * AMP  ;
    }
    else
    {
        return k *  (slvolume/100.0);
    }
}
0
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6813 / 2053 / 238
Регистрация: 14.12.2014
Сообщений: 4,313
Записей в блоге: 12
20.12.2025, 12:47
zorxor, зачем вы установили ASIOIndex=1, да ещё и с RememberASIOIndex=1? Может, вам стоит поменять настройку в проекте?

У меня стоит ASIO Link. Может, он как-то тоже влияет на это, х/з. Исключение возникает через секунду после открытия окна. Я даже не знаю, почему оно вообще открывается.

P.S. Я не особо хочу погружаться во всё это, так что изучайте сами. Мне было интересно просто потыкать прогу и всё, чисто из любопытства. Не потому, что есть какая-то необходимость.
Миниатюры
Программа-синтезатор   Программа-синтезатор  
0
 Аватар для zorxor
620 / 111 / 0
Регистрация: 09.02.2020
Сообщений: 2,696
05.02.2026, 22:49  [ТС]
Цитата Сообщение от Jin X Посмотреть сообщение
zorxor, зачем вы установили ASIOIndex=1, да ещё и с RememberASIOIndex=1? Может, вам стоит поменять настройку в проекте?
Да, вы абсолютно правы, это баг. Просто дело в том, что во время активной разработки я не обратил на это внимание, эти настройки завязаны были конкретно на мой комп, где я и занимался разработкой. Но, по большому счёту, приложение при первом своём запуске на конкретном компьютере должно выдавать диалоговое окно с просьбой выбрать пользователем нужной индекс устройства ASIO.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.02.2026, 22:49
Помогаю со студенческими работами здесь

Синтезатор
Всем привет! Помогите, пожалуйста, решить задачу. Вожусь уже 3 день, не могу понять, как её делать. Написать программу «синтезатор»....

Синтезатор программный
Подскажите где можно скачать или название приличного, повторюсь качественного синтезатора звука основных музыкальных инструментов(пианино,...

Синтезатор речи
люди подскажите как сделать синтезатор речи? какие нужны библиотеки.

Синтезатор речи
Здравствуйте, помогите пожалуйста а возможно ли сделать программу для синтезатора речи или для расшифровки текста с колонок? Заранее...

Синтезатор частот
Здравствуйте, мне нужен реализовать синтезатор частот в матлабе кодом(не Симулинк), но я даже не знаю с чего вообще можно начать...схема...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
[golang] Двоичная куча, min-heap
alhaos 20.05.2026
Двоичная куча Двоичная куча — структура данных, которая всегда держит самый важный элемент наготове. Представьте очередь к хилеру в игре, и очередь из игроков в приоритете те у кого меньше. . .
[golang] Breadth-First Search
alhaos 19.05.2026
BFS (Breadth-First Search) — это базовый алгоритм обхода графа в ширину, который поуровнево исследует все связанные вершины. Он начинает с выбранной точки и проверяет всех соседей, прежде чем. . .
[golang] Алгоритм «Хак Госпера»
alhaos 17.05.2026
Алгоритм «Хак Госпера» Хак Госпера (Gosper's Hack) — алгоритм нахождения следующего по величине числа с тем же количеством установленных бит. Придуман Биллом Госпером в 1970-х, опубликован в. . .
Рисование бинарного древа до 6-го колена на js, svg.
russiannick 17.05.2026
<svg width="335" height="240" viewBox="0 0 335 240" fill="#e5e1bb"> <style> <!]> </ style> <g id="bush"> </ g> </ svg> function fn(){ let rost;/ / высота древа let xx=165,yy=210,w=256;
FSharp: interface of module
DevAlt 16.05.2026
Интерфейс модуля F# позволяет управлять доступностью членов, содержащихся в реализации модуля. По-умолчанию все члены модуля доступны: module Foo let x = 10 let boo () = printfn "boo" . . .
Хитросплетение родственных связей пантеона греческих богов.
russiannick 14.05.2026
Однооконник, позволяющий узреть и изучить отдельных героев древней Греции. <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible". . .
[golang] Угол между стрелками часов
alhaos 12.05.2026
По заданным значениям часа и минуты необходимо определить значение меньшего угла между стрелками аналогового циферблата часов. import "math" func angleClock(hour int, minutes int) float64 { . . .
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru