r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / arender.C
blob6a1919779b384065fd584452098509a31bfb3420
1 #include "amodule.h"
2 #include "arender.h"
3 #include "atrack.h"
4 #include "atrack.h"
5 #include "audiodevice.h"
6 #include "auto.h"
7 #include "autos.h"
8 #include "cache.h"
9 #include "edit.h"
10 #include "edl.h"
11 #include "edlsession.h"
12 #include "levelwindow.h"
13 #include "mainsession.h"
14 #include "playabletracks.h"
15 #include "playbackengine.h"
16 #include "preferences.h"
17 #include "renderengine.h"
18 #include "tracks.h"
19 #include "transportque.h"
20 #include "virtualaconsole.h"
21 #include "virtualconsole.h"
22 #include "virtualnode.h"
24 ARender::ARender(RenderEngine *renderengine)
25  : CommonRender(renderengine)
27 // Clear output buffers
28         for(int i = 0; i < MAXCHANNELS; i++)
29         {
30                 audio_out[i] = 0;
31                 level_history[i] = 0;
32         }
33         level_samples = 0;
34         total_peaks = 0;
36         data_type = TRACK_AUDIO;
39 ARender::~ARender()
41         for(int i = 0; i < MAXCHANNELS; i++)
42         {
43 //printf("ARender::~ARender %p %p\n", audio_out[i], level_history[i]);
44                 if(audio_out[i]) delete [] audio_out[i];
45                 if(level_history[i]) delete [] level_history[i];
46         }
47         if(level_samples) delete [] level_samples;
50 void ARender::arm_command()
52 //printf("ARender::arm_command  1\n");
53         CommonRender::arm_command();
54 //printf("ARender::arm_command  1\n");
55         asynchronous = 1;
56 //printf("ARender::arm_command  1\n");
57         init_meters();
58 //printf("ARender::arm_command  2\n");
62 int ARender::get_total_tracks()
64         return renderengine->edl->tracks->total_audio_tracks();
67 Module* ARender::new_module(Track *track)
69 //printf("VirtualAConsole::new_module %p\n", track);
70         return new AModule(renderengine, this, 0, track);
73 int ARender::history_size()
75         if(total_peaks > 0) 
76                 return total_peaks;
77         else
78         {
79                 meter_render_fragment = renderengine->edl->session->audio_module_fragment;
80                 while(meter_render_fragment > renderengine->edl->session->sample_rate / 10) 
81                         meter_render_fragment /= 2;
82                 total_peaks = 2 * 
83                         renderengine->edl->session->audio_read_length / 
84                         meter_render_fragment;
85                 return total_peaks;
86         }
89 int ARender::init_meters()
91 // not providing enough peaks results in peaks that are ahead of the sound
92 //printf("ARender::init_meters 1\n");
93         if(level_samples) delete [] level_samples;
94         level_samples = new int64_t[history_size()];
95         for(int i = 0; i < MAXCHANNELS;i++)
96         {
97                 current_level[i] = 0;
98                 if(audio_out[i] && !level_history[i]) level_history[i] = new double[total_peaks];
99         }
101 //printf("ARender::init_meters 2\n");
102         for(int i = 0; i < history_size(); i++)
103         {
104                 level_samples[i] = -1;
105         }
106         
107         for(int j = 0; j < MAXCHANNELS; j++)
108         {
109                 if(audio_out[j]) 
110                         for(int i = 0; i < history_size(); i++)
111                                 level_history[j][i] = 0;
112         }
113         return 0;
116 void ARender::init_output_buffers()
118 //printf("ARender::init_output_buffers %d\n", renderengine->adjusted_fragment_len);
119         if(renderengine->command->realtime)
120         {
121                 for(int i = 0; i < MAXCHANNELS; i++)
122                 {
123 // Reset the output buffers in case speed changed
124                         if(audio_out[i])
125                         {
126                                 delete [] audio_out[i];
127                                 audio_out[i] = 0;
128                         }
130 //printf("ARender::init_output_buffers %d %d\n", i, renderengine->config->aconfig->do_channel[i]);
131                         if(renderengine->config->aconfig->do_channel[i])
132                         {
133                                 audio_out[i] = new double[renderengine->adjusted_fragment_len];
134                         }
135                 }
136         }
140 VirtualConsole* ARender::new_vconsole_object() 
142         return new VirtualAConsole(renderengine, this);
145 int64_t ARender::tounits(double position, int round)
147         if(round)
148                 return Units::round(position * renderengine->edl->session->sample_rate);
149         else
150                 return (int64_t)(position * renderengine->edl->session->sample_rate);
153 double ARender::fromunits(int64_t position)
155         return (double)position / renderengine->edl->session->sample_rate;
159 int ARender::process_buffer(double **buffer_out, 
160         int64_t input_len, 
161         int64_t input_position, 
162         int last_buffer)
164         int result = 0;
165 //printf("ARender::process_buffer 1\n");
166         this->last_playback = last_buffer;
167         int64_t fragment_position = 0;
168         int64_t fragment_len = input_len;
169         int reconfigure = 0;
170         current_position = input_position;
172 //printf("ARender::process_buffer 2\n");
173         while(fragment_position < input_len)
174         {
175                 for(int i = 0; i < MAXCHANNELS; i++)
176                 {
177                         if(buffer_out[i])
178                                 this->audio_out[i] = buffer_out[i] + fragment_position;
179                         else
180                                 this->audio_out[i] = 0;
181                 }
183                 fragment_len = input_len;
184                 if(fragment_position + fragment_len > input_len)
185                         fragment_len = input_len - fragment_position;
187 //printf("ARender::process_buffer 3 %d\n", fragment_len);
188                 reconfigure = vconsole->test_reconfigure(input_position, 
189                         fragment_len,
190                         last_playback);
192 //printf("ARender::process_buffer 4 %d %d %d\n", input_position, fragment_len, reconfigure);
195                 if(reconfigure) restart_playback();
196 //printf("ARender::process_buffer 6\n");
198                 result = process_buffer(fragment_len, input_position);
199 //printf("ARender::process_buffer 7\n");
201                 fragment_position += fragment_len;
202                 input_position += fragment_len;
203                 current_position = input_position;
204         }
206 // Don't delete audio_out on completion
207         bzero(this->audio_out, sizeof(double*) * MAXCHANNELS);
208 // printf("ARender::process_buffer 1 %.2f %.2f %.2f %.2f %.2f\n", 
209 //      buffer_out[0][0], 
210 //      buffer_out[0][1], 
211 //      buffer_out[0][2], 
212 //      buffer_out[0][3], 
213 //      buffer_out[0][4]);
214 //printf("ARender::process_buffer 8\n");
215         return result;
216         return 0;
220 int ARender::process_buffer(int64_t input_len, int64_t input_position)
222 //printf("ARender::process_buffer 1\n");
223         int result = ((VirtualAConsole*)vconsole)->process_buffer(input_len,
224                 input_position,
225                 last_playback,
226                 session_position);
233 // advance counters
234         session_position += input_len;
235         return result;
238 int ARender::restart_playback()
240 // Use for rebuilding the virtual console during playback.
241 // Send last buffer to old thread.
242         if(vconsole)
243         {
244                 send_reconfigure_buffer();
245                 vconsole->wait_for_completion();
246         }
248         CommonRender::restart_playback();
249         return 0;
252 int ARender::get_history_number(int64_t *table, int64_t position)
254 // Get the entry closest to position
255         int result = 0;
256         int64_t min_difference = 0x7fffffff;
257         for(int i = 0; i < history_size(); i++)
258         {
259 //printf("%d %d ", i, table[i]);
260                 if(labs(table[i] - position) < min_difference)
261                 {
262 //printf("\n");
263                         min_difference = labs(table[i] - position);
264                         result = i;
265                 }
266         }
267 //printf("\n");
268 //printf("ARender::get_history_number %ld %d %d\n", position, result, min_difference);
269         return result;
273 int ARender::wait_device_completion()
275 // audio device should be entirely cleaned up by vconsole
276         renderengine->audio->wait_for_completion();
277         return 0;
280 void ARender::run()
282         int64_t current_input_length;
283         int reconfigure = 0;
284 //printf("ARender::run 1\n");
286 //sleep(1);
287         start_lock.unlock();
289 //printf("ARender::run 2 %d %d %d\n", done, interrupt, last_playback);
290         while(!done && !interrupt && !last_playback)
291         {
292                 current_input_length = renderengine->edl->session->audio_read_length;
293 //printf("ARender::run 2 %d\n", current_input_length);
294                 get_boundaries(current_input_length);
295 //printf("ARender::run 3 %d\n", current_input_length);
297                 if(current_input_length)
298                 {
299 //printf("ARender::run 4 %d\n", current_input_length);
300                         reconfigure = vconsole->test_reconfigure(current_position, 
301                                 current_input_length,
302                                 last_playback);
303 //printf("ARender::run 5 %d %d\n", reconfigure, current_input_length);
304                         
305                         
306                         
307                         
308                         
309 //                      test_virtualnodes(current_position, 
310 //                              current_input_length, 
311 //                              get_datatype());
312                         if(reconfigure) restart_playback();
313                 }
314 //printf("ARender::run 4 %d %d %d\n", current_position, current_input_length, reconfigure);
317 // Update tracking if no video is playing.
318                 if(renderengine->command->realtime && 
319                         renderengine->playback_engine &&
320                         !renderengine->do_video)
321                 {
322                         double position = (double)renderengine->audio->current_position() / 
323                                 renderengine->edl->session->sample_rate * 
324                                 renderengine->command->get_speed();
326                         if(renderengine->command->get_direction() == PLAY_FORWARD) 
327                                 position += renderengine->command->playbackstart;
328                         else
329                                 position = renderengine->command->playbackstart - position;
331 //printf("ARender::run 6 %f\n", renderengine->audio->current_position());
332 // This number is not compensated for looping.  It's compensated in 
333 // PlaybackEngine::get_tracking_position when interpolation also happens.
334                         renderengine->playback_engine->update_tracking(position);
335                 }
336 //printf("ARender::run 7 %d\n", current_position);
343                 process_buffer(current_input_length, current_position);
344 //printf("ARender::run 8 %d %d %d\n", done, interrupt, last_playback);
346                 advance_position(get_render_length(current_input_length));
347                 if(vconsole->interrupt) interrupt = 1;
348 //printf("ARender::run 9 %d %d %d\n", done, interrupt, last_playback);
349         }
351 //printf("ARender::run 10\n");
352         if(renderengine->command->realtime) wait_device_completion();
353 //printf("ARender::run 11\n");
354         vconsole->stop_rendering(0);
355 //printf("ARender::run 12\n");
375 int ARender::get_datatype()
377         return TRACK_AUDIO;
380 int ARender::arm_playback(int64_t current_position,
381                         int64_t input_length, 
382                         int64_t amodule_render_fragment, 
383                         int64_t playback_buffer, 
384                         int64_t output_length)
386         this->current_position = current_position;
387         this->input_length = input_length;
388         session_position = 0;
389         startup_lock.lock();
391         source_length = renderengine->end_position - renderengine->start_position;
394         if(renderengine->command->realtime)
395         {
396                 Thread::set_realtime(renderengine->edl->session->real_time_playback);
397                 init_meters();
398         }
401 // start reading input and sending to arenderthread
402 // only if there's an audio device
403         if(renderengine->command->realtime)     
404         {
405                 set_synchronous(1);
406                 start();
407         }
408         return 0;
411 int ARender::send_reconfigure_buffer()
413         if(renderengine->command->realtime)
414         {
415                 vconsole->output_lock[vconsole->current_input_buffer]->lock();
417                 vconsole->input_len[vconsole->current_input_buffer] = 0;
418                 vconsole->input_position[vconsole->current_input_buffer] = 0;
419                 vconsole->last_playback[vconsole->current_input_buffer] = 0;
420                 vconsole->last_reconfigure[vconsole->current_input_buffer] = 1;
422                 vconsole->input_lock[vconsole->current_input_buffer]->unlock();
423                 vconsole->swap_input_buffer();
424         }
425         return 0;
428 int ARender::reverse_buffer(double *buffer, int64_t len)
430         register int64_t start, end;
431         double temp;
433         for(start = 0, end = len - 1; end > start; start++, end--)
434         {
435                 temp = buffer[start];
436                 buffer[start] = buffer[end];
437                 buffer[end] = temp;
438         }
441 int ARender::get_next_peak(int current_peak)
443         current_peak++;
444         if(current_peak == total_peaks) current_peak = 0;
445         return current_peak;
448 int64_t ARender::get_render_length(int64_t current_render_length)
450         return current_render_length;
453 int ARender::wait_for_startup()
455         startup_lock.lock();
456         startup_lock.unlock();