4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "aattachmentpoint.h"
27 #include "automation.h"
28 #include "bcsignals.h"
32 #include "edlsession.h"
33 #include "floatautos.h"
39 #include "renderengine.h"
42 #include "transition.h"
43 #include "transportque.h"
44 #include "virtualaconsole.h"
45 #include "virtualanode.h"
50 VirtualANode::VirtualANode(RenderEngine *renderengine,
51 VirtualConsole *vconsole,
55 VirtualNode *parent_module)
56 : VirtualNode(renderengine,
63 for(int i = 0; i < MAXCHANNELS; i++)
65 pan_before[i] = pan_after[i] = 0;
69 VirtualANode::~VirtualANode()
77 VirtualNode* VirtualANode::create_module(Plugin *real_plugin,
81 return new VirtualANode(renderengine,
90 VirtualNode* VirtualANode::create_plugin(Plugin *real_plugin)
92 return new VirtualANode(renderengine,
102 int VirtualANode::read_data(Samples *output_temp,
104 int64_t start_position,
107 VirtualNode *previous_plugin = 0;
109 // Current edit in parent track
110 AEdit *parent_edit = 0;
111 if(parent_node && parent_node->track && renderengine)
113 int64_t edl_rate = renderengine->get_edl()->session->sample_rate;
114 int64_t start_position_project = (int64_t)(start_position *
118 parent_edit = (AEdit*)parent_node->track->edits->editof(start_position_project,
119 renderengine->command->get_direction(),
124 if(vconsole->debug_tree)
125 printf(" VirtualANode::read_data position=" _LD " rate=" _LD ""
126 " title=%s parent_node=%p parent_edit=%p\n",
127 start_position, sample_rate, track->title,
128 parent_node, parent_edit);
131 // This is a plugin on parent module with a preceeding effect.
132 // Get data from preceeding effect on parent module.
134 (previous_plugin = parent_node->get_previous_plugin(this)))
136 ((VirtualANode*)previous_plugin)->render(output_temp,
142 // The current node is the first plugin on parent module.
143 // The parent module has an edit to read from or the current node
144 // has no source to read from.
145 // Read data from parent module
146 if(parent_node && (parent_edit || !real_module))
148 ((VirtualANode*)parent_node)->read_data(output_temp,
155 // This is the first node in the tree
157 ((AModule*)real_module)->render(output_temp,
160 renderengine->command->get_direction(),
167 int VirtualANode::render(Samples *output_temp,
169 int64_t start_position,
173 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
174 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
177 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
178 render_as_module(arender->audio_out,
183 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
188 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
189 render_as_plugin(output_temp,
193 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
195 if(debug) printf("VirtualANode::render %d this=%p\n", __LINE__, this);
199 void VirtualANode::render_as_plugin(Samples *output_temp,
201 int64_t start_position,
206 !real_plugin->on) return;
208 // If we're the first plugin in the parent module, data needs to be read from
209 // what comes before the parent module. Otherwise, data needs to come from the
211 ((AAttachmentPoint*)attachment)->render(
213 plugin_buffer_number,
219 int VirtualANode::render_as_module(Samples **audio_out,
220 Samples *output_temp,
222 int64_t start_position,
225 int direction = renderengine->command->get_direction();
226 EDL *edl = vconsole->renderengine->get_edl();
229 // Process last subnode. This calls read_data, propogates up the chain
230 // of subnodes, and finishes the chain.
233 VirtualANode *node = (VirtualANode*)subnodes.values[subnodes.total - 1];
234 node->render(output_temp,
241 // Read data from previous entity
243 read_data(output_temp,
249 // for(int k = 0; k < len; k++)
251 // output_temp->get_data()[k] = (k / 10) % 2;
254 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
255 render_fade(output_temp->get_data(),
259 track->automation->autos[AUTOMATION_FADE],
262 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
264 // Get the peak but don't limit
265 // Calculate position relative to project for meters
266 int64_t project_sample_rate = edl->session->sample_rate;
267 int64_t start_position_project = start_position *
268 project_sample_rate /
270 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
271 if(real_module && renderengine->command->realtime)
273 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
274 // Starting sample of meter block
275 int64_t meter_render_start;
276 // Ending sample of meter block
277 int64_t meter_render_end;
278 // Number of samples in each meter fragment normalized to requested rate
279 int meter_render_fragment = arender->meter_render_fragment *
284 // Scan fragment in meter sized fragments
285 for(int i = 0; i < len; )
287 int current_level = ((AModule*)real_module)->current_level;
289 meter_render_start = i;
290 meter_render_end = i + meter_render_fragment;
291 if(meter_render_end > len)
292 meter_render_end = len;
293 // Number of samples into the fragment this meter sized fragment is,
294 // normalized to project sample rate.
295 int64_t meter_render_start_project = meter_render_start *
296 project_sample_rate /
299 // Scan meter sized fragment
300 double *output_samples = output_temp->get_data();
301 for( ; i < meter_render_end; i++)
303 double sample = fabs(output_samples[i]);
304 if(sample > peak) peak = sample;
307 ((AModule*)real_module)->level_history[current_level] =
309 ((AModule*)real_module)->level_samples[current_level] =
310 (direction == PLAY_FORWARD) ?
311 (start_position_project + meter_render_start_project) :
312 (start_position_project - meter_render_start_project);
313 ((AModule*)real_module)->current_level =
314 arender->get_next_peak(current_level);
317 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
319 // process pans and copy the output to the output channels
320 // Keep rendering unmuted fragments until finished.
321 int mute_position = 0;
323 for(int i = 0; i < len; )
326 int mute_fragment = len - i;
327 int mute_fragment_project = mute_fragment *
328 project_sample_rate /
330 start_position_project = start_position +
331 ((direction == PLAY_FORWARD) ? i : -i);
332 start_position_project = start_position_project *
333 project_sample_rate /
336 // How many samples until the next mute?
337 get_mute_fragment(start_position_project,
339 mute_fragment_project,
340 (Autos*)track->automation->autos[AUTOMATION_MUTE],
343 // Fragment is playable
352 double *buffer = audio_out[j]->get_data();
354 render_pan(output_temp->get_data() + mute_position,
355 buffer + mute_position,
359 (Autos*)track->automation->autos[AUTOMATION_PAN],
363 //printf("VirtualANode::render_as_module %d %lld\n", __LINE__, start_position);
368 len -= mute_fragment;
370 mute_position += mute_fragment;
372 if(debug) printf("VirtualANode::render_as_module %d\n", __LINE__);
377 int VirtualANode::render_fade(double *buffer, int64_t len,
378 int64_t input_position, int64_t sample_rate,
379 Autos *autos, int direction, int use_nudge)
382 FloatAuto *previous = 0;
384 EDL *edl = vconsole->renderengine->get_edl();
386 int64_t project_sample_rate = edl->session->sample_rate;
387 double to_project_rate = (double)project_sample_rate / sample_rate;
388 double to_sample_rate = (double)sample_rate / project_sample_rate;
391 input_position += track->nudge * to_sample_rate;
393 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
394 // Normalize input position to project sample rate here.
395 // Automation functions are general to video and audio so it
396 // can't normalize itself.
397 int64_t input_pos = input_position * to_project_rate;
398 int64_t len_project = len * to_project_rate;
400 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
401 if(((FloatAutos*)autos)->automation_is_constant(
402 input_pos, len_project, direction, fade_value))
404 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
405 double value = fade_value<=INFINITYGAIN ?
406 0. : DB::fromdb(fade_value);
407 if( EQUIV(value, 0.) ) {
408 for(int64_t i = 0; i < len; i++)
411 else if( !EQUIV(value, 1.) ) {
412 for(int64_t i = 0; i < len; i++)
415 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
419 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
420 for(int64_t i = 0; i < len; i++)
422 input_pos = input_position * to_project_rate;
424 fade_value = ((FloatAutos*)autos)->get_value(
425 input_pos, direction, previous, next);
427 double value = fade_value<=INFINITYGAIN ?
428 0. : DB::fromdb(fade_value);
429 if( EQUIV(value,0.) )
431 else if( !EQUIV(value,1.) ) {
435 if(direction == PLAY_FORWARD)
440 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
442 if(debug) printf("VirtualANode::render_fade %d\n", __LINE__);
447 int VirtualANode::render_pan(double *input, // start of input fragment
448 double *output, // start of output fragment
449 int64_t fragment_len, // fragment length in input scale
450 int64_t input_position, // starting sample of input buffer in project
451 int64_t sample_rate, // sample rate of input_position
458 double intercept = 1.0;
459 EDL *edl = vconsole->renderengine->get_edl();
460 int64_t project_sample_rate = edl->session->sample_rate;
461 double to_project_rate = (double)project_sample_rate / sample_rate;
462 double to_sample_rate = (double)sample_rate / project_sample_rate;
464 input_position += track->nudge * to_sample_rate;
466 for(int i = 0; i < fragment_len; )
468 int64_t len = fragment_len - i;
469 int64_t slope_len = len * to_project_rate;
470 int64_t input_pos = input_position * to_project_rate;
472 // Get slope intercept formula for next fragment
473 get_pan_automation(slope, intercept, input_pos,
474 slope_len, autos, channel, direction);
476 slope_len *= to_sample_rate;
477 slope = slope * to_sample_rate;
478 slope_len = MIN(slope_len, len - i);
480 //printf("VirtualANode::render_pan 3 %d " _LD " %f %p %p\n", i, slope_len, slope, output, input);
481 if(!EQUIV(slope, 0)) {
482 for(double j = 0; j < slope_len; j++, i++) {
483 value = slope * j + intercept;
484 output[i] += input[i] * value;
487 else if( EQUIV(intercept, 1) ) {
488 for(int j = 0; j < slope_len; j++, i++)
489 output[i] += input[i];
491 else if( !EQUIV(intercept, 0) ) {
492 for(int j = 0; j < slope_len; j++, i++)
493 output[i] += input[i] * intercept;
498 if(direction == PLAY_FORWARD)
499 input_position += slope_len;
501 input_position -= slope_len;
503 //printf("VirtualANode::render_pan 4\n");
510 void VirtualANode::get_pan_automation(double &slope,
512 int64_t input_position,
521 PanAuto *prev_keyframe = 0;
522 PanAuto *next_keyframe = 0;
523 prev_keyframe = (PanAuto*)autos->get_prev_auto(input_position,
525 (Auto* &)prev_keyframe);
526 next_keyframe = (PanAuto*)autos->get_next_auto(input_position,
528 (Auto* &)next_keyframe);
530 if(direction == PLAY_FORWARD)
532 // Two distinct automation points within range
533 if(next_keyframe->position > prev_keyframe->position)
535 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
536 ((double)next_keyframe->position - prev_keyframe->position);
537 intercept = ((double)input_position - prev_keyframe->position) * slope +
538 prev_keyframe->values[channel];
540 if(next_keyframe->position < input_position + slope_len)
541 slope_len = next_keyframe->position - input_position;
544 // One automation point within range
547 intercept = prev_keyframe->values[channel];
552 // Two distinct automation points within range
553 if(next_keyframe->position < prev_keyframe->position)
555 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
556 ((double)next_keyframe->position - prev_keyframe->position);
557 intercept = ((double)input_position - prev_keyframe->position) * slope +
558 prev_keyframe->values[channel];
560 if(next_keyframe->position > input_position - slope_len)
561 slope_len = input_position - next_keyframe->position;
564 // One automation point within range
567 intercept = next_keyframe->values[channel];