-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDynamicsChecker.lua
More file actions
203 lines (172 loc) · 7.48 KB
/
DynamicsChecker.lua
File metadata and controls
203 lines (172 loc) · 7.48 KB
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
-- Профессиональный скрипт анализа динамики инструментов
local dynamics_targets = {
vocal = {
rms_min = -24, rms_max = -12,
peak_min = -6, peak_max = -0.5,
description = "Вокал должен быть разборчивым и экспрессивным",
compression_tips = {
"Используйте многополосную компрессию для контроля разных частотных диапазонов",
"Ratio 2:1 - 4:1 для основной компрессии",
"Быстрая атака (1-5ms) для контроля пиков",
"Среднее восстановление (50-100ms) для естественности"
}
},
drums = {
rms_min = -18, rms_max = -10,
peak_min = -4, peak_max = -0.5,
description = "Ударные требуют чёткой и контролируемой динамики",
compression_tips = {
"Параллельная компрессия для плотности",
"Ratio 4:1 - 8:1 для контроля пиков",
"Быстрая атака (0.1-1ms) для точности",
"Быстрое восстановление (10-50ms) для энергичности"
}
}
-- Остальные инструменты по аналогии...
}
-- Расширенные типы инструментов для определения
local instrument_patterns = {
vocal = {"voc", "вок", "lead", "лид", "voice", "голос"},
drums = {"drum", "удар", "beat", "бит"},
bass = {"bass", "бас"},
guitar = {"git", "гит"},
synth = {"synth", "син", "pad", "пэд"},
keys = {"key", "клав", "piano", "пиан"}
}
-- Функция для определения типа инструмента
local function detectInstrumentType(track_name)
local lower_name = string.lower(track_name)
for type, patterns in pairs(instrument_patterns) do
for _, pattern in ipairs(patterns) do
if string.match(lower_name, pattern) then
return type
end
end
end
return nil
end
-- Функция для анализа фазовых проблем
local function analyzePhaseIssues(track)
local phase_problems = false
local correlation = reaper.Track_GetPeakHoldDB(track, 2, false)
if correlation and correlation < 0 then
phase_problems = true
end
return phase_problems
end
function AnalyzeTrackDynamics(track)
local retval, track_name = reaper.GetTrackName(track)
-- Сохраняем текущую позицию
local cur_pos = reaper.GetCursorPosition()
reaper.PreventUIRefresh(1)
-- Получаем базовые параметры трека
local peak_val = reaper.Track_GetPeakInfo(track, 0)
local rms_l = reaper.Track_GetPeakHoldDB(track, 0, true)
local rms_r = reaper.Track_GetPeakHoldDB(track, 1, true)
local avg_rms = (rms_l + rms_r) / 2
-- Анализируем фазу
local phase_issues = analyzePhaseIssues(track)
-- Получаем параметры громкости
local volume = reaper.GetMediaTrackInfo_Value(track, "D_VOL")
local pan = reaper.GetMediaTrackInfo_Value(track, "D_PAN")
local width = reaper.GetMediaTrackInfo_Value(track, "D_WIDTH")
-- Определяем тип инструмента
local track_type = detectInstrumentType(track_name)
-- Анализируем эффекты на треке
local fx_count = reaper.TrackFX_GetCount(track)
local has_compressor = false
local has_limiter = false
for fx = 0, fx_count - 1 do
local retval, fx_name = reaper.TrackFX_GetFXName(track, fx, "")
local fx_lower = string.lower(fx_name)
if string.match(fx_lower, "comp") then
has_compressor = true
elseif string.match(fx_lower, "limit") then
has_limiter = true
end
end
-- Формируем результат анализа
local result = {
name = track_name,
type = track_type,
peak = 20 * math.log(peak_val, 10),
rms = avg_rms,
volume = 20 * math.log(volume, 10),
pan = pan,
width = width,
phase_issues = phase_issues,
has_compressor = has_compressor,
has_limiter = has_limiter
}
return result
end
function GenerateReport(analysis_results)
local report = "📊 АНАЛИЗ ДИНАМИКИ\n\n"
for _, result in ipairs(analysis_results) do
report = report .. string.format("🎵 Дорожка: %s\n", result.name)
report = report .. string.format("📈 Пиковый уровень: %.1f dB\n", result.peak)
report = report .. string.format("📊 RMS уровень: %.1f dB\n", result.rms)
report = report .. string.format("🎚️ Громкость: %.1f dB\n", result.volume)
if math.abs(result.pan) > 0.5 then
report = report .. string.format("↔️ Панорама: %.0f%%\n", result.pan * 100)
end
if result.width ~= 1.0 then
report = report .. string.format("↔️ Ширина стерео: %.0f%%\n", result.width * 100)
end
if result.phase_issues then
report = report .. "⚠️ Обнаружены проблемы с фазой!\n"
end
-- Информация об эффектах
if result.has_compressor then
report = report .. "🔸 Есть компрессор\n"
else
report = report .. "⚠️ Нет компрессора\n"
end
if result.has_limiter then
report = report .. "🔸 Есть лимитер\n"
end
if result.type and dynamics_targets[result.type] then
local target = dynamics_targets[result.type]
report = report .. "\n📝 РЕКОМЕНДАЦИИ:\n"
report = report .. target.description .. "\n"
-- Проверка RMS
if result.rms < target.rms_min then
report = report .. string.format("⚠️ RMS слишком низкий (%.1f dB). Рекомендуется поднять на %.1f dB\n",
result.rms, target.rms_min - result.rms)
elseif result.rms > target.rms_max then
report = report .. string.format("⚠️ RMS слишком высокий (%.1f dB). Рекомендуется снизить на %.1f dB\n",
result.rms, result.rms - target.rms_max)
end
-- Советы по компрессии
if not result.has_compressor then
report = report .. "\nРекомендации по компрессии:\n"
for _, tip in ipairs(target.compression_tips) do
report = report .. " • " .. tip .. "\n"
end
end
end
report = report .. "\n" .. string.rep("━", 50) .. "\n\n"
end
return report
end
function Main()
local project = 0
local track_count = reaper.CountTracks(project)
local results = {}
-- Начинаем анализ
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock()
for i = 0, track_count - 1 do
local track = reaper.GetTrack(project, i)
local analysis = AnalyzeTrackDynamics(track)
table.insert(results, analysis)
end
-- Генерируем и показываем отчет
local report = GenerateReport(results)
reaper.ShowMessageBox(report, "Анализ динамики", 0)
reaper.Undo_EndBlock("Анализ динамики", -1)
reaper.PreventUIRefresh(-1)
reaper.UpdateArrange()
end
-- Запускаем скрипт
Main()