Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

virtualanode.C

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

Generated on Sun Jan 8 13:39:02 2006 for Cinelerra-svn by  doxygen 1.4.4