1 #include "aattachmentpoint.h"
5 #include "automation.h"
7 #include "edlsession.h"
9 #include "floatautos.h"
14 #include "renderengine.h"
16 #include "transition.h"
17 #include "transportque.h"
18 #include "virtualaconsole.h"
19 #include "virtualanode.h"
24 VirtualANode::VirtualANode(RenderEngine *renderengine,
25 VirtualConsole *vconsole,
29 VirtualNode *parent_module)
30 : VirtualNode(renderengine,
37 for(int i = 0; i < MAXCHANNELS; i++)
39 pan_before[i] = pan_after[i] = 0;
43 VirtualANode::~VirtualANode()
51 VirtualNode* VirtualANode::create_module(Plugin *real_plugin,
55 return new VirtualANode(renderengine,
64 VirtualNode* VirtualANode::create_plugin(Plugin *real_plugin)
66 return new VirtualANode(renderengine,
76 int VirtualANode::read_data(double *output_temp,
77 int64_t start_position,
81 VirtualNode *previous_plugin = 0;
83 //printf("VirtualANode::read_data 1 %p\n", this);
84 // This is a plugin on parent module with a preceeding effect.
85 // Get data from preceeding effect on parent module.
86 if(parent_node && (previous_plugin = parent_node->get_previous_plugin(this)))
88 //printf("VirtualANode::read_data 2\n");
89 ((VirtualANode*)previous_plugin)->render(output_temp,
93 //printf("VirtualANode::read_data 3\n");
96 // First plugin on parent module.
97 // Read data from parent module
100 ((VirtualANode*)parent_node)->read_data(output_temp,
106 // This is the first node in the tree
108 //printf("VirtualANode::read_data 8\n");
109 ((AModule*)real_module)->render(output_temp,
112 renderengine->command->get_direction(),
115 //printf("VirtualANode::read_data 9\n");
117 //printf("VirtualANode::read_data 100 %p\n", this);
121 int VirtualANode::render(double *output_temp,
122 int64_t start_position,
126 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
129 //printf("VirtualANode::render 1\n");
130 render_as_module(arender->audio_out,
135 //printf("VirtualANode::render 2\n");
140 //printf("VirtualANode::render 3\n");
141 render_as_plugin(output_temp,
145 //printf("VirtualANode::render 4\n");
150 void VirtualANode::render_as_plugin(double *output_temp,
151 int64_t start_position,
155 //printf("VirtualANode::render_as_plugin 1 %p\n", this);
158 !real_plugin->on) return;
160 //printf("VirtualANode::render_as_plugin 2 %p\n", output_temp);
161 // If we're the first plugin in the parent module, data needs to be read from
162 // what comes before the parent module. Otherwise, data needs to come from the
164 ((AAttachmentPoint*)attachment)->render(
166 plugin_buffer_number,
170 //printf("VirtualANode::render_as_plugin 100 %p\n", this);
173 int VirtualANode::render_as_module(double **audio_out,
175 int64_t start_position,
180 int direction = renderengine->command->get_direction();
181 EDL *edl = vconsole->renderengine->edl;
184 // Process last subnode. This calls read_data, propogates up the chain
185 // of subnodes, and finishes the chain.
188 VirtualANode *node = (VirtualANode*)subnodes.values[subnodes.total - 1];
189 node->render(output_temp,
195 // Read data from previous entity
197 read_data(output_temp,
204 render_fade(output_temp,
208 track->automation->fade_autos,
212 // Get the peak but don't limit
213 // Calculate position relative to project for meters
214 int64_t project_sample_rate = edl->session->sample_rate;
215 int64_t start_position_project = start_position *
216 project_sample_rate /
218 if(real_module && renderengine->command->realtime)
220 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
221 // Starting sample of meter block
222 int64_t meter_render_start;
223 // Ending sample of meter block
224 int64_t meter_render_end;
225 // Number of samples in each meter fragment normalized to requested rate
226 int meter_render_fragment = arender->meter_render_fragment *
231 // Scan fragment in meter sized fragments
232 for(int i = 0; i < len; )
234 int current_level = ((AModule*)real_module)->current_level;
236 meter_render_start = i;
237 meter_render_end = i + meter_render_fragment;
238 if(meter_render_end > len)
239 meter_render_end = len;
240 // Number of samples into the fragment this meter sized fragment is,
241 // normalized to project sample rate.
242 int64_t meter_render_start_project = meter_render_start *
243 project_sample_rate /
246 // Scan meter sized fragment
247 for( ; i < meter_render_end; i++)
249 double sample = fabs(output_temp[i]);
250 if(sample > peak) peak = sample;
253 ((AModule*)real_module)->level_history[current_level] =
255 ((AModule*)real_module)->level_samples[current_level] =
256 (direction == PLAY_FORWARD) ?
257 (start_position_project + meter_render_start_project) :
258 (start_position_project - meter_render_start_project);
259 ((AModule*)real_module)->current_level =
260 arender->get_next_peak(current_level);
264 // process pans and copy the output to the output channels
265 // Keep rendering unmuted fragments until finished.
266 int mute_position = 0;
268 for(int i = 0; i < len; )
271 int mute_fragment = len - i;
272 int mute_fragment_project = mute_fragment *
273 project_sample_rate /
275 start_position_project = start_position +
276 ((direction == PLAY_FORWARD) ? i : -i);
277 start_position_project = start_position_project *
278 project_sample_rate /
281 // How many samples until the next mute?
282 get_mute_fragment(start_position_project,
284 mute_fragment_project,
285 (Autos*)track->automation->mute_autos,
288 // Fragment is playable
297 double *buffer = audio_out[j];
299 render_pan(output_temp + mute_position,
300 buffer + mute_position,
304 (Autos*)track->automation->pan_autos,
312 len -= mute_fragment;
314 mute_position += mute_fragment;
320 int VirtualANode::render_fade(double *buffer,
322 int64_t input_position,
328 double value, fade_value;
329 FloatAuto *previous = 0;
331 EDL *edl = vconsole->renderengine->edl;
332 int64_t project_sample_rate = edl->session->sample_rate;
333 if(use_nudge) input_position += track->nudge *
337 // Normalize input position to project sample rate here.
338 // Automation functions are general to video and audio so it
339 // can't normalize itself.
340 int64_t input_position_project = input_position *
341 project_sample_rate /
343 int64_t len_project = len *
344 project_sample_rate /
347 if(((FloatAutos*)autos)->automation_is_constant(input_position_project,
352 if(fade_value <= INFINITYGAIN)
355 value = DB::fromdb(fade_value);
356 for(int64_t i = 0; i < len; i++)
363 for(int64_t i = 0; i < len; i++)
365 int64_t slope_len = len - i;
366 input_position_project = input_position *
367 project_sample_rate /
370 fade_value = ((FloatAutos*)autos)->get_value(input_position_project,
375 if(fade_value <= INFINITYGAIN)
378 value = DB::fromdb(fade_value);
382 if(direction == PLAY_FORWARD)
392 int VirtualANode::render_pan(double *input, // start of input fragment
393 double *output, // start of output fragment
394 int64_t fragment_len, // fragment length in input scale
395 int64_t input_position, // starting sample of input buffer in project
396 int64_t sample_rate, // sample rate of input_position
403 double intercept = 1.0;
404 EDL *edl = vconsole->renderengine->edl;
405 int64_t project_sample_rate = edl->session->sample_rate;
406 if(use_nudge) input_position += track->nudge *
410 for(int i = 0; i < fragment_len; )
412 int64_t slope_len = (fragment_len - i) *
413 project_sample_rate /
416 // Get slope intercept formula for next fragment
417 get_pan_automation(slope,
420 project_sample_rate /
427 slope_len = slope_len * sample_rate / project_sample_rate;
428 slope = slope * sample_rate / project_sample_rate;
429 slope_len = MIN(slope_len, fragment_len - i);
431 //printf("VirtualANode::render_pan 3 %d %lld %f %p %p\n", i, slope_len, slope, output, input);
434 for(double j = 0; j < slope_len; j++, i++)
436 value = slope * j + intercept;
437 output[i] += input[i] * value;
442 for(int j = 0; j < slope_len; j++, i++)
444 output[i] += input[i] * intercept;
449 if(direction == PLAY_FORWARD)
450 input_position += slope_len;
452 input_position -= slope_len;
454 //printf("VirtualANode::render_pan 4\n");
461 void VirtualANode::get_pan_automation(double &slope,
463 int64_t input_position,
472 PanAuto *prev_keyframe = 0;
473 PanAuto *next_keyframe = 0;
474 prev_keyframe = (PanAuto*)autos->get_prev_auto(input_position, direction, (Auto*&)prev_keyframe);
475 next_keyframe = (PanAuto*)autos->get_next_auto(input_position, direction, (Auto*&)next_keyframe);
477 if(direction == PLAY_FORWARD)
479 // Two distinct automation points within range
480 if(next_keyframe->position > prev_keyframe->position)
482 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
483 ((double)next_keyframe->position - prev_keyframe->position);
484 intercept = ((double)input_position - prev_keyframe->position) * slope +
485 prev_keyframe->values[channel];
487 if(next_keyframe->position < input_position + slope_len)
488 slope_len = next_keyframe->position - input_position;
491 // One automation point within range
494 intercept = prev_keyframe->values[channel];
499 // Two distinct automation points within range
500 if(next_keyframe->position < prev_keyframe->position)
502 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
503 ((double)next_keyframe->position - prev_keyframe->position);
504 intercept = ((double)input_position - prev_keyframe->position) * slope +
505 prev_keyframe->values[channel];
507 if(next_keyframe->position > input_position - slope_len)
508 slope_len = input_position - next_keyframe->position;
511 // One automation point within range
514 intercept = next_keyframe->values[channel];