r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / cinelerra / virtualanode.C
blobb3e8750c1a3c4c3034ea1b6da6209039cc723456
1 #include "aattachmentpoint.h"
2 #include "amodule.h"
3 #include "arender.h"
4 #include "atrack.h"
5 #include "automation.h"
6 #include "edl.h"
7 #include "edlsession.h"
8 #include "floatautos.h"
9 #include "mwindow.h"
10 #include "module.h"
11 #include "plugin.h"
12 #include "renderengine.h"
13 #include "track.h"
14 #include "transition.h"
15 #include "transportque.h"
16 #include "virtualaconsole.h"
17 #include "virtualanode.h"
20 #include <string.h>
22 VirtualANode::VirtualANode(RenderEngine *renderengine, 
23                 VirtualConsole *vconsole, 
24                 Module *real_module, 
25                 Plugin *real_plugin,
26                 Track *track, 
27                 VirtualNode *parent_module, 
28                 double *buffer_in[],
29                 double *buffer_out[],
30                 int input_is_master,
31                 int output_is_master,
32                 int in,
33                 int out)
34  : VirtualNode(renderengine, 
35                 vconsole, 
36                 real_module, 
37                 real_plugin,
38                 track, 
39                 parent_module, 
40                 input_is_master,
41                 output_is_master,
42                 in,
43                 out)
45         for(int i = 0; i < RING_BUFFERS; i++)
46         {
47                 this->buffer_in[i] = buffer_in[i];
48                 this->buffer_out[i] = buffer_out[i];
49         }
51         for(int i = 0; i < MAXCHANNELS; i++)
52         {
53                 pan_before[i] = pan_after[i] = 0;
54         }
57 VirtualANode::~VirtualANode()
59         if(!shared_output) delete [] buffer_out[0];
60         if(!shared_input) delete [] buffer_in[0];
70 VirtualNode* VirtualANode::create_module(Plugin *real_plugin, 
71                                                         Module *real_module, 
72                                                         Track *track)
74         return new VirtualANode(renderengine, 
75                 vconsole, 
76                 real_module,
77                 0,
78                 track,
79                 this,
80                 data_in_input ? buffer_in : buffer_out,
81                 buffer_out,
82                 data_in_input ? input_is_master : output_is_master,
83                 output_is_master,
84                 real_plugin->in,
85                 real_plugin->out);
89 VirtualNode* VirtualANode::create_plugin(Plugin *real_plugin)
91         return new VirtualANode(renderengine, 
92                 vconsole, 
93                 0,
94                 real_plugin,
95                 track,
96                 this,
97                 data_in_input ? buffer_in : buffer_out,
98                 buffer_out,
99                 data_in_input ? input_is_master : output_is_master,
100                 output_is_master,
101                 real_plugin->in,
102                 real_plugin->out);
106 void VirtualANode::new_output_buffer()
108         buffer_out[0] = new double[renderengine->edl->session->audio_module_fragment];
111 void VirtualANode::new_input_buffer()
113         buffer_in[0] = new double[renderengine->edl->session->audio_module_fragment];
116 double* VirtualANode::get_module_input(int ring_buffer, int64_t fragment_offset)
118         double *result;
119         if(data_in_input)
120         {
121                 if(input_is_master) 
122                         result = buffer_in[ring_buffer] + fragment_offset;
123                 else
124                         result = buffer_in[0];
125         }
126         else
127         {
128                 if(output_is_master)
129                         result = buffer_out[ring_buffer] + fragment_offset;
130                 else
131                         result = buffer_out[0];
132         }
133         return result;
136 double* VirtualANode::get_module_output(int ring_buffer, int64_t fragment_position)
138         double *result;
140         if(output_is_master)
141                 result = buffer_out[ring_buffer] + fragment_position;
142         else
143                 result = buffer_out[0];
145         return result;
148 int VirtualANode::render(double **audio_out, 
149                                 int64_t audio_out_position, 
150                                 int ring_buffer,
151                                 int64_t fragment_position,
152                                 int64_t fragment_len, 
153                                 int64_t real_position, 
154                                 int64_t source_length, 
155                                 int reverse,
156                                 ARender *arender)
158         if(real_module)
159         {
160                 render_as_module(audio_out, 
161                                 audio_out_position, 
162                                 ring_buffer,
163                                 fragment_position,
164                                 fragment_len, 
165                                 real_position, 
166                                 arender);
167         }
168         else
169         if(real_plugin)
170         {
171 //printf("VirtualANode::render 1\n");
172                 render_as_plugin(real_position,
173                                 fragment_position,
174                                 fragment_len,
175                                 ring_buffer);
176         }
177         return 0;
180 void VirtualANode::render_as_plugin(int64_t real_position, 
181         int64_t fragment_position, 
182         int64_t fragment_len,
183         int ring_buffer)
185 //printf("VirtualANode::render_as_plugin 1\n");
186         ((AAttachmentPoint*)attachment)->render(buffer_in[ring_buffer] + fragment_position, 
187                 buffer_out[ring_buffer] + fragment_position, 
188                 fragment_len, 
189                 real_position);
192 int VirtualANode::render_as_module(double **audio_out, 
193                                 int64_t audio_out_position, 
194                                 int ring_buffer,
195                                 int64_t fragment_position,
196                                 int64_t fragment_len, 
197                                 int64_t real_position, 
198                                 ARender *arender)
200         int in_output = 0;
201         double *buffer_in = get_module_input(ring_buffer, fragment_position);
202         double *buffer_out = get_module_output(ring_buffer, fragment_position);
203         int direction = renderengine->command->get_direction();
205 //printf("VirtualANode::render_as_module 1 %p\n", this->buffer_in[ring_buffer] + fragment_position);
207 // for(int i = 0; i < fragment_len; i++)
208 // {
209 // int16_t value = (int16_t)(buffer_in[i] * 32767);
210 // fwrite(&value, 2, 1, stdout);
211 // }
213 //printf("VirtualANode::render_as_module 1 %d\n", ring_buffer);
214 // Render fade
215         render_fade(buffer_in, 
216                                 buffer_out,
217                                 fragment_len,
218                                 real_position,
219                                 track->automation->fade_autos);
221 // Get the peak but don't limit
222 //printf("VirtualANode::render_as_module 1 %p %d\n", real_module, renderengine->command->realtime);
223         if(real_module && renderengine->command->realtime)
224         {
225                 ARender *arender = ((VirtualAConsole*)vconsole)->arender;
226                 double max = 0, min = 0, peak;
227                 int64_t meter_render_start; // Starting sample of meter block
228                 int64_t meter_render_end;   // Ending sample of meter block
229                 int64_t current_level = ((AModule*)real_module)->current_level;
231 //printf("VirtualANode::render_as_module 1 %p %p\n", ((AModule*)real_module), ((AModule*)real_module)->level_samples);
232 // Scan fragment in meter sized fragments
233                 for(int i = 0; i < fragment_len; )
234                 {
235                         meter_render_start = i;
236                         meter_render_end = i + arender->meter_render_fragment;
237                         if(meter_render_end > fragment_len) meter_render_end = fragment_len;
238                         max = 0;
239                         min = 0;
240                         
241                         for( ; i < meter_render_end; i++)
242                         {
243                                 if(buffer_out[i] > max) max = buffer_out[i];
244                                 else
245                                 if(buffer_out[i] < min) min = buffer_out[i];
246                         }
248                         if(fabs(max) > fabs(min)) 
249                                 peak = fabs(max);
250                         else
251                                 peak = fabs(min);
253                         ((AModule*)real_module)->level_history[current_level] = 
254                                 peak;
255                         ((AModule*)real_module)->level_samples[current_level] = 
256                                 (renderengine->command->get_direction() == PLAY_FORWARD) ?
257                                 (real_position + meter_render_start) :
258                                 (real_position - meter_render_start);
259 //printf("VirtualANode::render_as_module 2 %d\n", ((AModule*)real_module)->level_samples[current_level]);
260                         ((AModule*)real_module)->current_level = 
261                                 arender->get_next_peak(((AModule*)real_module)->current_level);
262                 }
263         }
265 //printf("VirtualANode::render_as_module 1\n");
266 // process pans and copy the output to the output channels
267 // Keep rendering unmuted fragments until finished.
268         int mute_constant;
269         int64_t mute_fragment;
270         int64_t mute_position = 0;
272         for(int i = 0; i < fragment_len; )
273         {
274                 mute_fragment = fragment_len - i;
276 // How many samples until the next mute?
277                 get_mute_fragment(real_position,
278                                 mute_constant, 
279                                 mute_fragment,
280                                 (Autos*)track->automation->mute_autos);
281 //printf("VirtualANode::render_as_module 1\n");
283 // Fragment is playable
284                 if(!mute_constant)
285                 {
286                         for(int i = 0; 
287                                 i < MAX_CHANNELS; 
288                                 i++)
289                         {
290 //printf("VirtualANode::render_as_module %d\n", i);
291                                 if(audio_out[i])
292                                 {
293                                         double *buffer = audio_out[i];
295                                         render_pan(buffer_out + mute_position, 
296                                                                 buffer + audio_out_position + mute_position,
297                                                                 mute_fragment,
298                                                                 real_position,
299                                                                 (Autos*)track->automation->pan_autos,
300                                                                 i);
301                                 }
302                         }
303                 }
305                 fragment_len -= mute_fragment;
306                 real_position += (direction == PLAY_REVERSE) ? -mute_fragment : mute_fragment;
307                 mute_position += mute_fragment;
308         }
309 //printf("VirtualANode::render_as_module 2\n");
310         return 0;
313 int VirtualANode::render_fade(double *input,        // start of input fragment
314                                                                 double *output,        // start of output fragment
315                                                                 int64_t fragment_len,      // fragment length in input scale
316                                                                 int64_t input_position, // starting sample of input buffer in project
317                                                                 Autos *autos)
319         double value, fade_value;
320         int direction = renderengine->command->get_direction();
321         FloatAuto *previous = 0;
322         FloatAuto *next = 0;
325         if(((FloatAutos*)autos)->automation_is_constant(input_position, 
326                 fragment_len,
327                 direction,
328                 fade_value))
329         {
330 //printf("VirtualANode::render_fade 1 %d %f\n", input_position, fade_value);
331                 if(fade_value <= INFINITYGAIN) 
332                         value = 0;
333                 else
334                         value = DB::fromdb(fade_value);
335                 for(int64_t i = 0; i < fragment_len; i++)
336                 {
337                         output[i] = input[i] * value;
338                 }
339         }
340         else
341         {
342 //printf("VirtualANode::render_fade 10 %d\n", input_position);
343                 for(int64_t i = 0; i < fragment_len; i++)
344                 {
345                         int64_t slope_len = fragment_len - i;
347                         fade_value = ((FloatAutos*)autos)->get_value(input_position, 
348                                 direction,
349                                 previous,
350                                 next);
352                         if(fade_value <= INFINITYGAIN)
353                                 value = 0;
354                         else
355                                 value = DB::fromdb(fade_value);
357                         output[i] = input[i] * value;
359                         if(direction == PLAY_FORWARD)
360                                 input_position++;
362                         else
363                                 input_position--;
364                 }
365         }
367 // Get slope intercept formula for next fragment
368 //              get_fade_automation(slope, 
369 //                                              intercept, 
370 //                                              input_position,
371 //                                              slope_len,
372 //                                              autos);
373 // 
374 //              if(slope != 0)
375 //              {
376 //                      for(double j = 0; 
377 //                              j < slope_len; 
378 //                              j++, i++)
379 //                      {
380 //                              value = slope * j + intercept;
381 //                              value = DB::fromdb(value);
382 //                              output[i] = input[i] * value;
383 //                      }
384 //              }
385 //              else
386 //              {
387 //                      double value = DB::fromdb(intercept);
388 //                      for(int j = 0; 
389 //                              j < slope_len; 
390 //                              j++, i++)
391 //                      {
392 //                              output[i] = input[i] * value;
393 //                      }
394 //              }
395 // 
396 // 
397 //              if(direction == PLAY_FORWARD)
398 //                      input_position += slope_len;
399 //              else
400 //                      input_position -= slope_len;
401 //      }
403         return 0;
406 int VirtualANode::render_pan(double *input,        // start of input fragment
407                                                                 double *output,        // start of output fragment
408                                                                 int64_t fragment_len,      // fragment length in input scale
409                                                                 int64_t input_position, // starting sample of input buffer in project
410                                                                 Autos *autos,
411                                                                 int channel)
413         double slope, intercept;
414         int direction = renderengine->command->get_direction();
416         for(int64_t i = 0; i < fragment_len; )
417         {
418                 int64_t slope_len = fragment_len - i;
420 // Get slope intercept formula for next fragment
421                 get_pan_automation(slope, 
422                                                 intercept, 
423                                                 input_position,
424                                                 slope_len,
425                                                 autos,
426                                                 channel);
428                 if(slope != 0)
429                 {
430                         for(double j = 0; j < slope_len; j++, i++)
431                         {
432                                 value = slope * j + intercept;
433                                 output[i] += input[i] * value;
434                         }
435                 }
436                 else
437                 {
438                         for(int j = 0; j < slope_len; j++, i++)
439                         {
440                                 output[i] += input[i] * intercept;
441                         }
442                 }
445                 if(direction == PLAY_FORWARD)
446                         input_position += slope_len;
447                 else
448                         input_position -= slope_len;
449         }
451 // if(channel == 0)
452 // for(int i = 0; i < fragment_len; i++)
453 // {
454 // int16_t value = (int16_t)(input[i] * 32767);
455 // fwrite(&value, 2, 1, stdout);
456 // }
458         return 0;