Blender V5.0
sequencer/intern/sound.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2009 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
10
11#include <algorithm>
12#include <cmath>
13#include <cstring>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_curve_types.h"
18#include "DNA_scene_types.h"
19#include "DNA_sequence_types.h"
20#include "DNA_sound_types.h"
21
22#include "BLI_listbase.h"
23#include "BLI_utildefines.h"
24
25#include "BKE_colortools.hh"
26#include "BKE_sound.h"
27
28#ifdef WITH_CONVOLUTION
29# include "AUD_Sound.h"
30#endif
31
32#include "SEQ_sequencer.hh"
33#include "SEQ_sound.hh"
34#include "SEQ_time.hh"
35
36#include "strip_time.hh"
37
38namespace blender::seq {
39
40/* Unlike _update_sound_ functions,
41 * these ones take info from audaspace to update sequence length! */
44
45#ifdef WITH_CONVOLUTION
46static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, ListBase *seqbase)
47{
48 bool changed = false;
49
50 LISTBASE_FOREACH (Strip *, strip, seqbase) {
51 if (strip->type == STRIP_TYPE_META) {
52 if (sequencer_refresh_sound_length_recursive(bmain, scene, &strip->seqbase)) {
53 changed = true;
54 }
55 }
56 else if (strip->type == STRIP_TYPE_SOUND_RAM && strip->sound) {
57 SoundInfo info;
58 if (!BKE_sound_info_get(bmain, strip->sound, &info)) {
59 continue;
60 }
61
62 int old = strip->len;
63 float fac;
64
65 strip->len = std::max(
66 1, int(round((info.length - strip->sound->offset_time) * scene->frames_per_second())));
67 fac = float(strip->len) / float(old);
68 old = strip->startofs;
69 strip->startofs *= fac;
70 strip->endofs *= fac;
71 strip->start += (old -
72 strip->startofs); /* So that visual/"real" start frame does not change! */
73
74 changed = true;
75 }
76 }
77 return changed;
78}
79#endif
80
81void sound_update_length(Main *bmain, Scene *scene)
82{
83#ifdef WITH_CONVOLUTION
84 if (scene->ed) {
85 sequencer_refresh_sound_length_recursive(bmain, scene, &scene->ed->seqbase);
86 }
87#else
88 UNUSED_VARS(bmain, scene);
89#endif
90}
91
93{
94 Editing *ed = scene->ed;
95
96 if (ed) {
97 LISTBASE_FOREACH (Strip *, strip, &ed->seqbase) {
98 if (strip->type == STRIP_TYPE_META) {
100 }
101 else if (ELEM(strip->type, STRIP_TYPE_SOUND_RAM, STRIP_TYPE_SCENE)) {
102 sound_update_bounds(scene, strip);
103 }
104 }
105 }
106}
107
108void sound_update_bounds(Scene *scene, Strip *strip)
109{
110 if (strip->type == STRIP_TYPE_SCENE) {
111 if (strip->scene && strip->scene_sound) {
112 /* We have to take into account start frame of the sequence's scene! */
113 int startofs = strip->startofs + strip->anim_startofs + strip->scene->r.sfra;
114
116 strip->scene_sound,
117 time_left_handle_frame_get(scene, strip),
118 time_right_handle_frame_get(scene, strip),
119 startofs,
120 0.0);
121 }
122 }
123 else {
125 }
126 /* mute is set in strip_update_muting_recursive */
127}
128
129static void strip_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
130{
131 LISTBASE_FOREACH (Strip *, strip, seqbasep) {
132 if (strip->type == STRIP_TYPE_META) {
133 strip_update_sound_recursive(scene, &strip->seqbase, sound);
134 }
135 else if (strip->type == STRIP_TYPE_SOUND_RAM) {
136 if (strip->scene_sound && sound == strip->sound) {
137 BKE_sound_update_scene_sound(strip->scene_sound, sound);
138 }
139 }
140 }
141}
142
143void sound_update(Scene *scene, bSound *sound)
144{
145 if (scene->ed) {
146 strip_update_sound_recursive(scene, &scene->ed->seqbase, sound);
147 }
148}
149
150float sound_pitch_get(const Scene *scene, const Strip *strip)
151{
152 const Strip *meta_parent = lookup_meta_by_strip(scene->ed, strip);
153 if (meta_parent != nullptr) {
154 return strip->speed_factor * sound_pitch_get(scene, meta_parent);
155 }
156 return strip->speed_factor;
157}
158
160{
161 EQCurveMappingData *eqcmd;
162
163 if (maxX < 0) {
165 }
166 if (minX < 0) {
167 minX = 0.0;
168 }
169 /* It's the same as #BKE_curvemapping_add, but changing the name. */
170 eqcmd = MEM_callocN<EQCurveMappingData>("Equalizer");
172 1, /* Total. */
173 minX,
174 -SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Min x, y */
175 maxX,
176 SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Max x, y */
178
180
181 rctf clipr;
182 clipr.xmin = minX;
183 clipr.xmax = maxX;
184 clipr.ymin = 0.0;
185 clipr.ymax = 0.0;
186
188 &clipr,
191
192 BLI_addtail(&semd->graphics, eqcmd);
193
194 return eqcmd;
195}
196
198{
200 if (number == 1) {
202 }
203 else if (number == 2) {
204 sound_equalizer_add(semd, 30.0, 2000.0);
205 sound_equalizer_add(semd, 2000.1, 20000.0);
206 }
207 else if (number == 3) {
208 sound_equalizer_add(semd, 30.0, 1000.0);
209 sound_equalizer_add(semd, 1000.1, 5000.0);
210 sound_equalizer_add(semd, 5000.1, 20000.0);
211 }
212}
213
215 float min_freq,
216 float max_freq)
217{
218 if (min_freq < 0.0) {
219 return nullptr;
220 }
221 if (max_freq < 0.0) {
222 return nullptr;
223 }
224 if (max_freq <= min_freq) {
225 return nullptr;
226 }
227 return sound_equalizer_add(semd, min_freq, max_freq);
228}
229
236
243
245{
248 BKE_curvemapping_free_data(&eqcmd->curve_mapping);
249 MEM_freeN(eqcmd);
250 }
252 if (smd->runtime.last_buf) {
254 }
255}
256
258{
261 EQCurveMappingData *eqcmd_n;
262
263 BLI_listbase_clear(&semd_target->graphics);
264
265 LISTBASE_FOREACH (EQCurveMappingData *, eqcmd, &semd->graphics) {
266 eqcmd_n = static_cast<EQCurveMappingData *>(MEM_dupallocN(eqcmd));
267 BKE_curvemapping_copy_data(&eqcmd_n->curve_mapping, &eqcmd->curve_mapping);
268
269 eqcmd_n->next = eqcmd_n->prev = nullptr;
270 BLI_addtail(&semd_target->graphics, eqcmd_n);
271 }
272}
273
276 void *sound_in,
277 bool &needs_update)
278{
279#ifdef WITH_CONVOLUTION
280 UNUSED_VARS(strip);
281
283
284 /* No equalizer definition. */
285 if (BLI_listbase_is_empty(&semd->graphics)) {
286 return sound_in;
287 }
288
290
291 CurveMapping *eq_mapping;
292 CurveMap *cm;
293 float minX;
294 float maxX;
296
297 /* Visit all equalizer definitions. */
298 LISTBASE_FOREACH (EQCurveMappingData *, mapping, &semd->graphics) {
299 eq_mapping = &mapping->curve_mapping;
300 BKE_curvemapping_init(eq_mapping);
301 cm = eq_mapping->cm;
302 minX = eq_mapping->curr.xmin;
303 maxX = eq_mapping->curr.xmax;
304 int idx = int(ceil(minX / interval));
305 int i = idx;
306 for (; i * interval <= maxX && i < SOUND_EQUALIZER_SIZE_DEFINITION; i++) {
307 float freq = i * interval;
308 float val = BKE_curvemap_evaluateF(eq_mapping, cm, freq);
310 val = (val / fabs(val)) * SOUND_EQUALIZER_DEFAULT_MAX_DB;
311 }
312 buf[i] = val;
313 /* To soften lower limit, but not the first position which is the constant value */
314 if (i == idx && i > 2) {
315 buf[i - 1] = 0.5 * (buf[i] + buf[i - 1]);
316 }
317 }
318 /* To soften higher limit */
320 buf[i] = 0.5 * (buf[i] + buf[i - 1]);
321 }
322 }
323
324 /* Only make new sound when necessary. It is faster and it prevents audio glitches. */
325 if (!needs_update && smd->runtime.last_sound_in == sound_in &&
326 smd->runtime.last_buf != nullptr &&
327 std::memcmp(buf, smd->runtime.last_buf, SOUND_EQUALIZER_SIZE_DEFINITION) == 0)
328 {
329 MEM_freeN(buf);
330 return smd->runtime.last_sound_out;
331 }
332
333 AUD_Sound *sound_out = AUD_Sound_equalize(sound_in,
334 buf,
338
339 needs_update = true;
340 smd->runtime.last_buf = buf;
341 smd->runtime.last_sound_in = sound_in;
342 smd->runtime.last_sound_out = sound_out;
343
344 return sound_out;
345#else
346 UNUSED_VARS(strip, smd, sound_in, needs_update);
347 return nullptr;
348#endif
349}
350
352{
353 for (int i = 0; workersSoundModifiers[i].type > 0; i++) {
354 if (workersSoundModifiers[i].type == type) {
355 return &workersSoundModifiers[i];
356 }
357 }
358 return nullptr;
359}
360
363 void *sound,
364 bool &needs_update)
365{
366
367 if (!(smd->flag & STRIP_MODIFIER_FLAG_MUTE)) {
369 return smwi->recreator(strip, smd, sound, needs_update);
370 }
371 return sound;
372}
373
374} // namespace blender::seq
void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, CurveMapSlopeType slope)
void BKE_curvemapping_free_data(CurveMapping *cumap)
void BKE_curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy, short default_handle_type)
Definition colortools.cc:40
void BKE_curvemapping_init(CurveMapping *cumap)
float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value)
void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
bool BKE_sound_info_get(struct Main *main, struct bSound *sound, SoundInfo *sound_info)
struct SoundInfo SoundInfo
void BKE_sound_move_scene_sound(const struct Scene *scene, void *handle, int startframe, int endframe, int frameskip, double audio_offset)
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound)
void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Strip *sequence)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
bool BLI_remlink_safe(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:154
#define UNUSED_VARS(...)
#define ELEM(...)
@ CURVE_PRESET_CONSTANT_MEDIAN
@ HD_AUTO_ANIM
@ eSeqModifierType_SoundEqualizer
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_SOUND_RAM
@ STRIP_TYPE_META
@ STRIP_MODIFIER_FLAG_MUTE
Read Guarded memory(de)allocation.
#define SOUND_EQUALIZER_DEFAULT_MAX_FREQ
Definition SEQ_sound.hh:30
#define SOUND_EQUALIZER_SIZE_CONVERSION
Definition SEQ_sound.hh:32
#define SOUND_EQUALIZER_SIZE_DEFINITION
Definition SEQ_sound.hh:33
#define SOUND_EQUALIZER_DEFAULT_MIN_FREQ
Definition SEQ_sound.hh:29
#define SOUND_EQUALIZER_DEFAULT_MAX_DB
Definition SEQ_sound.hh:31
nullptr float
#define round
#define ceil
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 fabs(const float2 a)
Strip * lookup_meta_by_strip(Editing *ed, const Strip *key)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
void sound_update_bounds_all(Scene *scene)
void sound_equalizermodifier_init_data(StripModifierData *smd)
EQCurveMappingData * sound_equalizer_add(SoundEqualizerModifierData *semd, float minX, float maxX)
void sound_update_length(Main *bmain, Scene *scene)
const SoundModifierWorkerInfo workersSoundModifiers[]
int time_left_handle_frame_get(const Scene *, const Strip *strip)
void sound_equalizermodifier_remove_graph(SoundEqualizerModifierData *semd, EQCurveMappingData *eqcmd)
void sound_equalizermodifier_free(StripModifierData *smd)
EQCurveMappingData * sound_equalizermodifier_add_graph(SoundEqualizerModifierData *semd, float min_freq, float max_freq)
void sound_update_bounds(Scene *scene, Strip *strip)
void * sound_modifier_recreator(Strip *strip, StripModifierData *smd, void *sound, bool &needs_update)
void strip_update_sound_bounds_recursive(const Scene *scene, Strip *strip_meta)
float sound_pitch_get(const Scene *scene, const Strip *strip)
void sound_equalizermodifier_copy_data(StripModifierData *target, StripModifierData *smd)
void sound_equalizermodifier_set_graphs(SoundEqualizerModifierData *semd, int number)
void sound_update(Scene *scene, bSound *sound)
static void strip_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
void * sound_equalizermodifier_recreator(Strip *strip, StripModifierData *smd, void *sound_in, bool &needs_update)
const SoundModifierWorkerInfo * sound_modifier_worker_info_get(int type)
CurveMap cm[4]
struct EQCurveMappingData * next
struct EQCurveMappingData * prev
struct CurveMapping curve_mapping
ListBase seqbase
struct Editing * ed
struct RenderData r
float length
Definition BKE_sound.h:79
StripModifierDataRuntime runtime
void * scene_sound
struct Scene * scene
float speed_factor
void *(* recreator)(Strip *strip, StripModifierData *smd, void *sound, bool &needs_update)
Definition SEQ_sound.hh:26
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230