00001 #include "aattachmentpoint.h"
00002 #include "aedit.h"
00003 #include "amodule.h"
00004 #include "arender.h"
00005 #include "atrack.h"
00006 #include "automation.h"
00007 #include "edits.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "clip.h"
00011 #include "floatautos.h"
00012 #include "mwindow.h"
00013 #include "module.h"
00014 #include "panauto.h"
00015 #include "plugin.h"
00016 #include "renderengine.h"
00017 #include "track.h"
00018 #include "transition.h"
00019 #include "transportque.h"
00020 #include "virtualaconsole.h"
00021 #include "virtualanode.h"
00022
00023
00024 #include <string.h>
00025
00026 VirtualANode::VirtualANode(RenderEngine *renderengine,
00027 VirtualConsole *vconsole,
00028 Module *real_module,
00029 Plugin *real_plugin,
00030 Track *track,
00031 VirtualNode *parent_module)
00032 : VirtualNode(renderengine,
00033 vconsole,
00034 real_module,
00035 real_plugin,
00036 track,
00037 parent_module)
00038 {
00039 for(int i = 0; i < MAXCHANNELS; i++)
00040 {
00041 pan_before[i] = pan_after[i] = 0;
00042 }
00043 }
00044
00045 VirtualANode::~VirtualANode()
00046 {
00047 }
00048
00049
00050
00051
00052
00053 VirtualNode* VirtualANode::create_module(Plugin *real_plugin,
00054 Module *real_module,
00055 Track *track)
00056 {
00057 return new VirtualANode(renderengine,
00058 vconsole,
00059 real_module,
00060 0,
00061 track,
00062 this);
00063 }
00064
00065
00066 VirtualNode* VirtualANode::create_plugin(Plugin *real_plugin)
00067 {
00068 return new VirtualANode(renderengine,
00069 vconsole,
00070 0,
00071 real_plugin,
00072 track,
00073 this);
00074 }
00075
00076
00077
00078 int VirtualANode::read_data(double *output_temp,
00079 int64_t start_position,
00080 int64_t len,
00081 int64_t sample_rate)
00082 {
00083 VirtualNode *previous_plugin = 0;
00084
00085
00086 AEdit *parent_edit = 0;
00087 if(parent_node && parent_node->track && renderengine)
00088 {
00089 int64_t edl_rate = renderengine->edl->session->sample_rate;
00090 int64_t start_position_project = (int64_t)(start_position *
00091 edl_rate /
00092 sample_rate +
00093 0.5);
00094 parent_edit = (AEdit*)parent_node->track->edits->editof(start_position_project,
00095 renderengine->command->get_direction(),
00096 0);
00097 }
00098
00099
00100 if(vconsole->debug_tree)
00101 printf(" VirtualANode::read_data position=%lld rate=%lld title=%s parent_node=%p parent_edit=%p\n",
00102 start_position,
00103 sample_rate,
00104 track->title,
00105 parent_node,
00106 parent_edit);
00107
00108
00109
00110
00111 if(parent_node &&
00112 (previous_plugin = parent_node->get_previous_plugin(this)))
00113 {
00114 ((VirtualANode*)previous_plugin)->render(output_temp,
00115 start_position,
00116 len,
00117 sample_rate);
00118 }
00119 else
00120
00121
00122
00123
00124 if(parent_node && (parent_edit || !real_module))
00125 {
00126 ((VirtualANode*)parent_node)->read_data(output_temp,
00127 start_position,
00128 len,
00129 sample_rate);
00130 }
00131 else
00132 if(real_module)
00133
00134 {
00135 ((AModule*)real_module)->render(output_temp,
00136 start_position,
00137 len,
00138 renderengine->command->get_direction(),
00139 sample_rate,
00140 0);
00141 }
00142 return 0;
00143 }
00144
00145 int VirtualANode::render(double *output_temp,
00146 int64_t start_position,
00147 int64_t len,
00148 int64_t sample_rate)
00149 {
00150 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
00151 if(real_module)
00152 {
00153 render_as_module(arender->audio_out,
00154 output_temp,
00155 start_position,
00156 len,
00157 sample_rate);
00158 }
00159 else
00160 if(real_plugin)
00161 {
00162 render_as_plugin(output_temp,
00163 start_position,
00164 len,
00165 sample_rate);
00166 }
00167 return 0;
00168 }
00169
00170 void VirtualANode::render_as_plugin(double *output_temp,
00171 int64_t start_position,
00172 int64_t len,
00173 int64_t sample_rate)
00174 {
00175 if(!attachment ||
00176 !real_plugin ||
00177 !real_plugin->on) return;
00178
00179
00180
00181
00182 ((AAttachmentPoint*)attachment)->render(
00183 output_temp,
00184 plugin_buffer_number,
00185 start_position,
00186 len,
00187 sample_rate);
00188 }
00189
00190 int VirtualANode::render_as_module(double **audio_out,
00191 double *output_temp,
00192 int64_t start_position,
00193 int64_t len,
00194 int64_t sample_rate)
00195 {
00196 int in_output = 0;
00197 int direction = renderengine->command->get_direction();
00198 EDL *edl = vconsole->renderengine->edl;
00199
00200
00201
00202
00203 if(subnodes.total)
00204 {
00205 VirtualANode *node = (VirtualANode*)subnodes.values[subnodes.total - 1];
00206 node->render(output_temp,
00207 start_position,
00208 len,
00209 sample_rate);
00210 }
00211 else
00212
00213 {
00214 read_data(output_temp,
00215 start_position,
00216 len,
00217 sample_rate);
00218 }
00219
00220
00221 render_fade(output_temp,
00222 len,
00223 start_position,
00224 sample_rate,
00225 track->automation->autos[AUTOMATION_FADE],
00226 direction,
00227 0);
00228
00229
00230
00231 int64_t project_sample_rate = edl->session->sample_rate;
00232 int64_t start_position_project = start_position *
00233 project_sample_rate /
00234 sample_rate;
00235 if(real_module && renderengine->command->realtime)
00236 {
00237 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
00238
00239 int64_t meter_render_start;
00240
00241 int64_t meter_render_end;
00242
00243 int meter_render_fragment = arender->meter_render_fragment *
00244 sample_rate /
00245 project_sample_rate;
00246
00247
00248
00249 for(int i = 0; i < len; )
00250 {
00251 int current_level = ((AModule*)real_module)->current_level;
00252 double peak = 0;
00253 meter_render_start = i;
00254 meter_render_end = i + meter_render_fragment;
00255 if(meter_render_end > len)
00256 meter_render_end = len;
00257
00258
00259 int64_t meter_render_start_project = meter_render_start *
00260 project_sample_rate /
00261 sample_rate;
00262
00263
00264 for( ; i < meter_render_end; i++)
00265 {
00266 double sample = fabs(output_temp[i]);
00267 if(sample > peak) peak = sample;
00268 }
00269
00270 ((AModule*)real_module)->level_history[current_level] =
00271 peak;
00272 ((AModule*)real_module)->level_samples[current_level] =
00273 (direction == PLAY_FORWARD) ?
00274 (start_position_project + meter_render_start_project) :
00275 (start_position_project - meter_render_start_project);
00276 ((AModule*)real_module)->current_level =
00277 arender->get_next_peak(current_level);
00278 }
00279 }
00280
00281
00282
00283 int mute_position = 0;
00284
00285 for(int i = 0; i < len; )
00286 {
00287 int mute_constant;
00288 int mute_fragment = len - i;
00289 int mute_fragment_project = mute_fragment *
00290 project_sample_rate /
00291 sample_rate;
00292 start_position_project = start_position +
00293 ((direction == PLAY_FORWARD) ? i : -i);
00294 start_position_project = start_position_project *
00295 project_sample_rate /
00296 sample_rate;
00297
00298
00299 get_mute_fragment(start_position_project,
00300 mute_constant,
00301 mute_fragment_project,
00302 (Autos*)track->automation->autos[AUTOMATION_MUTE],
00303 direction,
00304 0);
00305
00306 if(!mute_constant)
00307 {
00308 for(int j = 0;
00309 j < MAX_CHANNELS;
00310 j++)
00311 {
00312 if(audio_out[j])
00313 {
00314 double *buffer = audio_out[j];
00315
00316 render_pan(output_temp + mute_position,
00317 buffer + mute_position,
00318 mute_fragment,
00319 start_position,
00320 sample_rate,
00321 (Autos*)track->automation->autos[AUTOMATION_PAN],
00322 j,
00323 direction,
00324 0);
00325 }
00326 }
00327 }
00328
00329 len -= mute_fragment;
00330 i += mute_fragment;
00331 mute_position += mute_fragment;
00332 }
00333
00334 return 0;
00335 }
00336
00337 int VirtualANode::render_fade(double *buffer,
00338 int64_t len,
00339 int64_t input_position,
00340 int64_t sample_rate,
00341 Autos *autos,
00342 int direction,
00343 int use_nudge)
00344 {
00345 double value, fade_value;
00346 FloatAuto *previous = 0;
00347 FloatAuto *next = 0;
00348 EDL *edl = vconsole->renderengine->edl;
00349 int64_t project_sample_rate = edl->session->sample_rate;
00350 if(use_nudge) input_position += track->nudge *
00351 sample_rate /
00352 project_sample_rate;
00353
00354
00355
00356
00357 int64_t input_position_project = input_position *
00358 project_sample_rate /
00359 sample_rate;
00360 int64_t len_project = len *
00361 project_sample_rate /
00362 sample_rate;
00363
00364 if(((FloatAutos*)autos)->automation_is_constant(input_position_project,
00365 len_project,
00366 direction,
00367 fade_value))
00368 {
00369 if(fade_value <= INFINITYGAIN)
00370 value = 0;
00371 else
00372 value = DB::fromdb(fade_value);
00373 for(int64_t i = 0; i < len; i++)
00374 {
00375 buffer[i] *= value;
00376 }
00377 }
00378 else
00379 {
00380 for(int64_t i = 0; i < len; i++)
00381 {
00382 int64_t slope_len = len - i;
00383 input_position_project = input_position *
00384 project_sample_rate /
00385 sample_rate;
00386
00387 fade_value = ((FloatAutos*)autos)->get_value(input_position_project,
00388 direction,
00389 previous,
00390 next);
00391
00392 if(fade_value <= INFINITYGAIN)
00393 value = 0;
00394 else
00395 value = DB::fromdb(fade_value);
00396
00397 buffer[i] *= value;
00398
00399 if(direction == PLAY_FORWARD)
00400 input_position++;
00401 else
00402 input_position--;
00403 }
00404 }
00405
00406 return 0;
00407 }
00408
00409 int VirtualANode::render_pan(double *input,
00410 double *output,
00411 int64_t fragment_len,
00412 int64_t input_position,
00413 int64_t sample_rate,
00414 Autos *autos,
00415 int channel,
00416 int direction,
00417 int use_nudge)
00418 {
00419 double slope = 0.0;
00420 double intercept = 1.0;
00421 EDL *edl = vconsole->renderengine->edl;
00422 int64_t project_sample_rate = edl->session->sample_rate;
00423 if(use_nudge) input_position += track->nudge *
00424 sample_rate /
00425 project_sample_rate;
00426
00427 for(int i = 0; i < fragment_len; )
00428 {
00429 int64_t slope_len = (fragment_len - i) *
00430 project_sample_rate /
00431 sample_rate;
00432
00433
00434 get_pan_automation(slope,
00435 intercept,
00436 input_position *
00437 project_sample_rate /
00438 sample_rate,
00439 slope_len,
00440 autos,
00441 channel,
00442 direction);
00443
00444 slope_len = slope_len * sample_rate / project_sample_rate;
00445 slope = slope * sample_rate / project_sample_rate;
00446 slope_len = MIN(slope_len, fragment_len - i);
00447
00448
00449 if(!EQUIV(slope, 0))
00450 {
00451 for(double j = 0; j < slope_len; j++, i++)
00452 {
00453 value = slope * j + intercept;
00454 output[i] += input[i] * value;
00455 }
00456 }
00457 else
00458 {
00459 for(int j = 0; j < slope_len; j++, i++)
00460 {
00461 output[i] += input[i] * intercept;
00462 }
00463 }
00464
00465
00466 if(direction == PLAY_FORWARD)
00467 input_position += slope_len;
00468 else
00469 input_position -= slope_len;
00470
00471
00472 }
00473
00474 return 0;
00475 }
00476
00477
00478 void VirtualANode::get_pan_automation(double &slope,
00479 double &intercept,
00480 int64_t input_position,
00481 int64_t &slope_len,
00482 Autos *autos,
00483 int channel,
00484 int direction)
00485 {
00486 intercept = 0;
00487 slope = 0;
00488
00489 PanAuto *prev_keyframe = 0;
00490 PanAuto *next_keyframe = 0;
00491 prev_keyframe = (PanAuto*)autos->get_prev_auto(input_position,
00492 direction,
00493 (Auto* &)prev_keyframe);
00494 next_keyframe = (PanAuto*)autos->get_next_auto(input_position,
00495 direction,
00496 (Auto* &)next_keyframe);
00497
00498 if(direction == PLAY_FORWARD)
00499 {
00500
00501 if(next_keyframe->position > prev_keyframe->position)
00502 {
00503 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
00504 ((double)next_keyframe->position - prev_keyframe->position);
00505 intercept = ((double)input_position - prev_keyframe->position) * slope +
00506 prev_keyframe->values[channel];
00507
00508 if(next_keyframe->position < input_position + slope_len)
00509 slope_len = next_keyframe->position - input_position;
00510 }
00511 else
00512
00513 {
00514 slope = 0;
00515 intercept = prev_keyframe->values[channel];
00516 }
00517 }
00518 else
00519 {
00520
00521 if(next_keyframe->position < prev_keyframe->position)
00522 {
00523 slope = ((double)next_keyframe->values[channel] - prev_keyframe->values[channel]) /
00524 ((double)next_keyframe->position - prev_keyframe->position);
00525 intercept = ((double)input_position - prev_keyframe->position) * slope +
00526 prev_keyframe->values[channel];
00527
00528 if(next_keyframe->position > input_position - slope_len)
00529 slope_len = input_position - next_keyframe->position;
00530 }
00531 else
00532
00533 {
00534 slope = 0;
00535 intercept = next_keyframe->values[channel];
00536 }
00537 }
00538 }