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

arender.C

Go to the documentation of this file.
00001 #include "amodule.h"
00002 #include "arender.h"
00003 #include "atrack.h"
00004 #include "atrack.h"
00005 #include "audiodevice.h"
00006 #include "auto.h"
00007 #include "autos.h"
00008 #include "cache.h"
00009 #include "condition.h"
00010 #include "edit.h"
00011 #include "edl.h"
00012 #include "edlsession.h"
00013 #include "levelwindow.h"
00014 #include "mainsession.h"
00015 #include "playabletracks.h"
00016 #include "playbackengine.h"
00017 #include "preferences.h"
00018 #include "renderengine.h"
00019 #include "tracks.h"
00020 #include "transportque.h"
00021 #include "virtualaconsole.h"
00022 #include "virtualconsole.h"
00023 #include "virtualnode.h"
00024 
00025 ARender::ARender(RenderEngine *renderengine)
00026  : CommonRender(renderengine)
00027 {
00028 // Clear output buffers
00029         for(int i = 0; i < MAXCHANNELS; i++)
00030         {
00031                 audio_out[i] = 0;
00032                 level_history[i] = 0;
00033         }
00034         level_samples = 0;
00035         total_peaks = 0;
00036 
00037         data_type = TRACK_AUDIO;
00038 }
00039 
00040 ARender::~ARender()
00041 {
00042         for(int i = 0; i < MAXCHANNELS; i++)
00043         {
00044                 if(audio_out[i]) delete [] audio_out[i];
00045                 if(level_history[i]) delete [] level_history[i];
00046         }
00047         if(level_samples) delete [] level_samples;
00048 }
00049 
00050 void ARender::arm_command()
00051 {
00052 // Need the meter history now so AModule can allocate its own history
00053         calculate_history_size();
00054         CommonRender::arm_command();
00055         asynchronous = 1;
00056         init_meters();
00057 }
00058 
00059 
00060 int ARender::get_total_tracks()
00061 {
00062         return renderengine->edl->tracks->total_audio_tracks();
00063 }
00064 
00065 Module* ARender::new_module(Track *track)
00066 {
00067         return new AModule(renderengine, this, 0, track);
00068 }
00069 
00070 int ARender::calculate_history_size()
00071 {
00072         if(total_peaks > 0)
00073                 return total_peaks;
00074         else
00075         {
00076                 meter_render_fragment = renderengine->fragment_len;
00077 // This number and the timer in tracking.C determine the rate
00078                 while(meter_render_fragment > 
00079                         renderengine->edl->session->sample_rate / TRACKING_RATE) 
00080                         meter_render_fragment /= 2;
00081                 total_peaks = 16 * 
00082                         renderengine->fragment_len / 
00083                         meter_render_fragment;
00084                 return total_peaks;
00085         }
00086 }
00087 
00088 int ARender::init_meters()
00089 {
00090 // not providing enough peaks results in peaks that are ahead of the sound
00091         if(level_samples) delete [] level_samples;
00092         calculate_history_size();
00093         level_samples = new int64_t[total_peaks];
00094         for(int i = 0; i < MAXCHANNELS;i++)
00095         {
00096                 current_level[i] = 0;
00097                 if(audio_out[i] && !level_history[i]) level_history[i] = new double[total_peaks];
00098         }
00099 
00100         for(int i = 0; i < total_peaks; i++)
00101         {
00102                 level_samples[i] = -1;
00103         }
00104         
00105         for(int j = 0; j < MAXCHANNELS; j++)
00106         {
00107                 if(audio_out[j]) 
00108                         for(int i = 0; i < total_peaks; i++)
00109                                 level_history[j][i] = 0;
00110         }
00111         return 0;
00112 }
00113 
00114 void ARender::init_output_buffers()
00115 {
00116         if(renderengine->command->realtime)
00117         {
00118                 for(int i = 0; i < MAXCHANNELS; i++)
00119                 {
00120 // Reset the output buffers in case speed changed
00121                         if(audio_out[i])
00122                         {
00123                                 delete [] audio_out[i];
00124                                 audio_out[i] = 0;
00125                         }
00126 
00127                         if(renderengine->config->aconfig->do_channel[i])
00128                         {
00129                                 audio_out[i] = new double[renderengine->adjusted_fragment_len];
00130                         }
00131                 }
00132         }
00133 }
00134 
00135 
00136 VirtualConsole* ARender::new_vconsole_object() 
00137 { 
00138         return new VirtualAConsole(renderengine, this);
00139 }
00140 
00141 int64_t ARender::tounits(double position, int round)
00142 {
00143         if(round)
00144                 return Units::round(position * renderengine->edl->session->sample_rate);
00145         else
00146                 return (int64_t)(position * renderengine->edl->session->sample_rate);
00147 }
00148 
00149 double ARender::fromunits(int64_t position)
00150 {
00151         return (double)position / renderengine->edl->session->sample_rate;
00152 }
00153 
00154 
00155 int ARender::process_buffer(double **buffer_out, 
00156         int64_t input_len, 
00157         int64_t input_position, 
00158         int last_buffer)
00159 {
00160         int result = 0;
00161 
00162         this->last_playback = last_buffer;
00163         int64_t fragment_position = 0;
00164         int64_t fragment_len = input_len;
00165         int reconfigure = 0;
00166         current_position = input_position;
00167 
00168         while(fragment_position < input_len)
00169         {
00170                 for(int i = 0; i < MAXCHANNELS; i++)
00171                 {
00172                         if(buffer_out[i])
00173                                 this->audio_out[i] = buffer_out[i] + fragment_position;
00174                         else
00175                                 this->audio_out[i] = 0;
00176                 }
00177 
00178                 fragment_len = input_len;
00179                 if(fragment_position + fragment_len > input_len)
00180                         fragment_len = input_len - fragment_position;
00181 
00182                 reconfigure = vconsole->test_reconfigure(input_position, 
00183                         fragment_len,
00184                         last_playback);
00185 
00186 //printf("ARender::process_buffer 1 %lld %d\n", input_position, reconfigure);
00187 
00188                 if(reconfigure) restart_playback();
00189 
00190                 result = process_buffer(fragment_len, input_position);
00191 
00192                 fragment_position += fragment_len;
00193                 input_position += fragment_len;
00194                 current_position = input_position;
00195         }
00196 
00197 // Don't delete audio_out on completion
00198         bzero(this->audio_out, sizeof(double*) * MAXCHANNELS);
00199 
00200 
00201 
00202         return result;
00203         return 0;
00204 }
00205 
00206 
00207 int ARender::process_buffer(int64_t input_len, int64_t input_position)
00208 {
00209         int result = ((VirtualAConsole*)vconsole)->process_buffer(input_len,
00210                 input_position,
00211                 last_playback,
00212                 session_position);
00213 
00214 
00215 
00216 // advance counters
00217         session_position += input_len;
00218         return result;
00219 }
00220 
00221 int ARender::get_history_number(int64_t *table, int64_t position)
00222 {
00223 // Get the entry closest to position
00224         int result = 0;
00225         int64_t min_difference = 0x7fffffff;
00226         for(int i = 0; i < total_peaks; i++)
00227         {
00228 
00229 //printf("%lld ", table[i]);
00230                 if(labs(table[i] - position) < min_difference)
00231                 {
00232                         min_difference = labs(table[i] - position);
00233                         result = i;
00234                 }
00235         }
00236 //printf("\n");
00237 //printf("ARender::get_history_number %lld %d\n", position, result);
00238         return result;
00239 }
00240 
00241 void ARender::send_last_buffer()
00242 {
00243         renderengine->audio->set_last_buffer();
00244 }
00245 
00246 int ARender::wait_device_completion()
00247 {
00248 // audio device should be entirely cleaned up by vconsole
00249         renderengine->audio->wait_for_completion();
00250         return 0;
00251 }
00252 
00253 void ARender::run()
00254 {
00255         int64_t current_input_length;
00256         int reconfigure = 0;
00257 
00258         first_buffer = 1;
00259 
00260         start_lock->unlock();
00261 //printf("ARender::run 1 %d\n", Thread::calculate_realtime());
00262 
00263         while(!done && !interrupt && !last_playback)
00264         {
00265                 current_input_length = renderengine->fragment_len;
00266 
00267                 get_boundaries(current_input_length);
00268 
00269 //printf("ARender::run 10 %lld %lld\n", current_position, current_input_length);
00270                 if(current_input_length)
00271                 {
00272                         reconfigure = vconsole->test_reconfigure(current_position, 
00273                                 current_input_length,
00274                                 last_playback);
00275                         if(reconfigure) restart_playback();
00276                 }
00277 //printf("ARender::run 20 %lld %lld\n", current_position, current_input_length);
00278 
00279 
00280 // Update tracking if no video is playing.
00281                 if(renderengine->command->realtime && 
00282                         renderengine->playback_engine &&
00283                         !renderengine->do_video)
00284                 {
00285                         double position = (double)renderengine->audio->current_position() / 
00286                                 renderengine->edl->session->sample_rate * 
00287                                 renderengine->command->get_speed();
00288 
00289                         if(renderengine->command->get_direction() == PLAY_FORWARD) 
00290                                 position += renderengine->command->playbackstart;
00291                         else
00292                                 position = renderengine->command->playbackstart - position;
00293 
00294 // This number is not compensated for looping.  It's compensated in 
00295 // PlaybackEngine::get_tracking_position when interpolation also happens.
00296                         renderengine->playback_engine->update_tracking(position);
00297                 }
00298 
00299 
00300 
00301 //printf("ARender::run 30 %lld\n", current_input_length);
00302 
00303 
00304 
00305                 process_buffer(current_input_length, current_position);
00306 //printf("ARender::run 40\n");
00307 
00308 
00309                 advance_position(get_render_length(current_input_length));
00310 //printf("ARender::run 50\n");
00311 
00312 
00313                 if(vconsole->interrupt) interrupt = 1;
00314         }
00315 
00316         if(!interrupt) send_last_buffer();
00317         if(renderengine->command->realtime) wait_device_completion();
00318         vconsole->stop_rendering(0);
00319 }
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 int ARender::get_datatype()
00339 {
00340         return TRACK_AUDIO;
00341 }
00342 
00343 int ARender::arm_playback(int64_t current_position,
00344                         int64_t input_length, 
00345                         int64_t amodule_render_fragment, 
00346                         int64_t playback_buffer, 
00347                         int64_t output_length)
00348 {
00349         this->current_position = current_position;
00350         this->input_length = input_length;
00351         session_position = 0;
00352 
00353         source_length = renderengine->end_position - renderengine->start_position;
00354 
00355 
00356         if(renderengine->command->realtime)
00357         {
00358                 Thread::set_realtime(renderengine->edl->session->real_time_playback);
00359                 init_meters();
00360         }
00361 
00362 
00363 // start reading input and sending to arenderthread
00364 // only if there's an audio device
00365         if(renderengine->command->realtime)     
00366         {
00367                 set_synchronous(1);
00368                 start();
00369         }
00370         return 0;
00371 }
00372 
00373 // int ARender::send_reconfigure_buffer()
00374 // {
00375 //      if(renderengine->command->realtime)
00376 //      {
00377 //              vconsole->output_lock[vconsole->current_input_buffer]->lock("ARender::send_reconfigure_buffer");
00378 // 
00379 //              vconsole->input_len[vconsole->current_input_buffer] = 0;
00380 //              vconsole->input_position[vconsole->current_input_buffer] = 0;
00381 //              vconsole->last_playback[vconsole->current_input_buffer] = 0;
00382 //              vconsole->last_reconfigure[vconsole->current_input_buffer] = 1;
00383 // 
00384 //              vconsole->input_lock[vconsole->current_input_buffer]->unlock();
00385 //              vconsole->swap_input_buffer();
00386 //      }
00387 //      return 0;
00388 // }
00389 
00390 int ARender::reverse_buffer(double *buffer, int64_t len)
00391 {
00392         register int64_t start, end;
00393         double temp;
00394 
00395         for(start = 0, end = len - 1; end > start; start++, end--)
00396         {
00397                 temp = buffer[start];
00398                 buffer[start] = buffer[end];
00399                 buffer[end] = temp;
00400         }
00401 }
00402 
00403 int ARender::get_next_peak(int current_peak)
00404 {
00405         current_peak++;
00406         if(current_peak >= total_peaks) current_peak = 0;
00407         return current_peak;
00408 }
00409 
00410 int64_t ARender::get_render_length(int64_t current_render_length)
00411 {
00412         return current_render_length;
00413 }
00414 

Generated on Sun Jan 8 13:38:49 2006 for Cinelerra-svn by  doxygen 1.4.4