Blender V4.5
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(1, int(round((info.length - strip->sound->offset_time) * FPS)));
66 fac = float(strip->len) / float(old);
67 old = strip->startofs;
68 strip->startofs *= fac;
69 strip->endofs *= fac;
70 strip->start += (old -
71 strip->startofs); /* So that visual/"real" start frame does not change! */
72
73 changed = true;
74 }
75 }
76 return changed;
77}
78#endif
79
80void sound_update_length(Main *bmain, Scene *scene)
81{
82#ifdef WITH_CONVOLUTION
83 if (scene->ed) {
84 sequencer_refresh_sound_length_recursive(bmain, scene, &scene->ed->seqbase);
85 }
86#else
87 UNUSED_VARS(bmain, scene);
88#endif
89}
90
92{
93 Editing *ed = scene->ed;
94
95 if (ed) {
96 LISTBASE_FOREACH (Strip *, strip, &ed->seqbase) {
97 if (strip->type == STRIP_TYPE_META) {
99 }
100 else if (ELEM(strip->type, STRIP_TYPE_SOUND_RAM, STRIP_TYPE_SCENE)) {
101 sound_update_bounds(scene, strip);
102 }
103 }
104 }
105}
106
107void sound_update_bounds(Scene *scene, Strip *strip)
108{
109 if (strip->type == STRIP_TYPE_SCENE) {
110 if (strip->scene && strip->scene_sound) {
111 /* We have to take into account start frame of the sequence's scene! */
112 int startofs = strip->startofs + strip->anim_startofs + strip->scene->r.sfra;
113
115 strip->scene_sound,
116 time_left_handle_frame_get(scene, strip),
117 time_right_handle_frame_get(scene, strip),
118 startofs,
119 0.0);
120 }
121 }
122 else {
124 }
125 /* mute is set in strip_update_muting_recursive */
126}
127
128static void strip_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
129{
130 LISTBASE_FOREACH (Strip *, strip, seqbasep) {
131 if (strip->type == STRIP_TYPE_META) {
132 strip_update_sound_recursive(scene, &strip->seqbase, sound);
133 }
134 else if (strip->type == STRIP_TYPE_SOUND_RAM) {
135 if (strip->scene_sound && sound == strip->sound) {
136 BKE_sound_update_scene_sound(strip->scene_sound, sound);
137 }
138 }
139 }
140}
141
142void sound_update(Scene *scene, bSound *sound)
143{
144 if (scene->ed) {
145 strip_update_sound_recursive(scene, &scene->ed->seqbase, sound);
146 }
147}
148
149float sound_pitch_get(const Scene *scene, const Strip *strip)
150{
151 const Strip *meta_parent = lookup_meta_by_strip(scene->ed, strip);
152 if (meta_parent != nullptr) {
153 return strip->speed_factor * sound_pitch_get(scene, meta_parent);
154 }
155 return strip->speed_factor;
156}
157
159{
160 EQCurveMappingData *eqcmd;
161
162 if (maxX < 0) {
164 }
165 if (minX < 0) {
166 minX = 0.0;
167 }
168 /* It's the same as #BKE_curvemapping_add, but changing the name. */
169 eqcmd = MEM_callocN<EQCurveMappingData>("Equalizer");
171 1, /* Total. */
172 minX,
173 -SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Min x, y */
174 maxX,
175 SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Max x, y */
177
179
180 rctf clipr;
181 clipr.xmin = minX;
182 clipr.xmax = maxX;
183 clipr.ymin = 0.0;
184 clipr.ymax = 0.0;
185
187
188 BLI_addtail(&semd->graphics, eqcmd);
189
190 return eqcmd;
191}
192
194{
196 if (number == 1) {
198 }
199 else if (number == 2) {
200 sound_equalizer_add(semd, 30.0, 2000.0);
201 sound_equalizer_add(semd, 2000.1, 20000.0);
202 }
203 else if (number == 3) {
204 sound_equalizer_add(semd, 30.0, 1000.0);
205 sound_equalizer_add(semd, 1000.1, 5000.0);
206 sound_equalizer_add(semd, 5000.1, 20000.0);
207 }
208}
209
211 float min_freq,
212 float max_freq)
213{
214 if (min_freq < 0.0) {
215 return nullptr;
216 }
217 if (max_freq < 0.0) {
218 return nullptr;
219 }
220 if (max_freq <= min_freq) {
221 return nullptr;
222 }
223 return sound_equalizer_add(semd, min_freq, max_freq);
224}
225
232
239
249
251{
254 EQCurveMappingData *eqcmd_n;
255
256 BLI_listbase_clear(&semd_target->graphics);
257
258 LISTBASE_FOREACH (EQCurveMappingData *, eqcmd, &semd->graphics) {
259 eqcmd_n = static_cast<EQCurveMappingData *>(MEM_dupallocN(eqcmd));
260 BKE_curvemapping_copy_data(&eqcmd_n->curve_mapping, &eqcmd->curve_mapping);
261
262 eqcmd_n->next = eqcmd_n->prev = nullptr;
263 BLI_addtail(&semd_target->graphics, eqcmd_n);
264 }
265}
266
268{
269#ifdef WITH_CONVOLUTION
270 UNUSED_VARS(strip);
271
273
274 /* No equalizer definition. */
275 if (BLI_listbase_is_empty(&semd->graphics)) {
276 return sound;
277 }
278
280
281 CurveMapping *eq_mapping;
282 CurveMap *cm;
283 float minX;
284 float maxX;
286
287 /* Visit all equalizer definitions. */
288 LISTBASE_FOREACH (EQCurveMappingData *, mapping, &semd->graphics) {
289 eq_mapping = &mapping->curve_mapping;
290 BKE_curvemapping_init(eq_mapping);
291 cm = eq_mapping->cm;
292 minX = eq_mapping->curr.xmin;
293 maxX = eq_mapping->curr.xmax;
294 int idx = int(ceil(minX / interval));
295 int i = idx;
296 for (; i * interval <= maxX && i < SOUND_EQUALIZER_SIZE_DEFINITION; i++) {
297 float freq = i * interval;
298 float val = BKE_curvemap_evaluateF(eq_mapping, cm, freq);
300 val = (val / fabs(val)) * SOUND_EQUALIZER_DEFAULT_MAX_DB;
301 }
302 buf[i] = val;
303 /* To soften lower limit, but not the first position which is the constant value */
304 if (i == idx && i > 2) {
305 buf[i - 1] = 0.5 * (buf[i] + buf[i - 1]);
306 }
307 }
308 /* To soften higher limit */
310 buf[i] = 0.5 * (buf[i] + buf[i - 1]);
311 }
312 }
313
314 AUD_Sound *equ = AUD_Sound_equalize(sound,
315 buf,
319
320 MEM_freeN(buf);
321
322 return equ;
323#else
324 UNUSED_VARS(strip, smd, sound);
325 return nullptr;
326#endif
327}
328
330{
331 for (int i = 0; workersSoundModifiers[i].type > 0; i++) {
332 if (workersSoundModifiers[i].type == type) {
333 return &workersSoundModifiers[i];
334 }
335 }
336 return nullptr;
337}
338
339void *sound_modifier_recreator(Strip *strip, StripModifierData *smd, void *sound)
340{
341
342 if (!(smd->flag & SEQUENCE_MODIFIER_MUTE)) {
344 return smwi->recreator(strip, smd, sound);
345 }
346 return sound;
347}
348
349} // namespace blender::seq
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)
void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
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
#define FPS
@ SEQUENCE_MODIFIER_MUTE
@ STRIP_TYPE_SCENE
@ STRIP_TYPE_SOUND_RAM
@ STRIP_TYPE_META
@ seqModifierType_SoundEqualizer
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
#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_modifier_recreator(Strip *strip, StripModifierData *smd, void *sound)
void sound_update_bounds(Scene *scene, Strip *strip)
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)
void * sound_equalizermodifier_recreator(Strip *strip, StripModifierData *smd, void *sound)
static void strip_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
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
void * scene_sound
struct Scene * scene
float speed_factor
void *(* recreator)(Strip *strip, StripModifierData *smd, void *sound)
Definition SEQ_sound.hh:26
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230