4 * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "audiodevice.h"
28 #include "bcsignals.h"
30 #include "condition.h"
33 #include "edlsession.h"
34 #include "levelwindow.h"
35 #include "mainsession.h"
36 #include "playabletracks.h"
37 #include "playbackengine.h"
38 #include "preferences.h"
39 #include "renderengine.h"
42 #include "transportque.h"
43 #include "virtualaconsole.h"
44 #include "virtualconsole.h"
45 #include "virtualnode.h"
47 ARender::ARender(RenderEngine *renderengine)
48 : CommonRender(renderengine)
50 // Clear output buffers
51 for(int i = 0; i < MAXCHANNELS; i++)
55 buffer_allocated[i] = 0;
61 data_type = TRACK_AUDIO;
66 for(int i = 0; i < MAXCHANNELS; i++)
68 if(buffer[i]) delete buffer[i];
69 if(level_history[i]) delete [] level_history[i];
71 if(level_samples) delete [] level_samples;
74 void ARender::arm_command()
76 // Need the meter history now so AModule can allocate its own history
77 calculate_history_size();
78 CommonRender::arm_command();
84 int ARender::get_total_tracks()
86 return renderengine->get_edl()->tracks->total_audio_tracks();
89 Module* ARender::new_module(Track *track)
91 return new AModule(renderengine, this, 0, track);
94 int ARender::calculate_history_size()
100 meter_render_fragment = renderengine->fragment_len;
101 // This number and the timer in tracking.C determine the rate
102 while(meter_render_fragment >
103 renderengine->get_edl()->session->sample_rate / TRACKING_RATE)
104 meter_render_fragment /= 2;
106 renderengine->fragment_len /
107 meter_render_fragment;
112 int ARender::init_meters()
114 // not providing enough peaks results in peaks that are ahead of the sound
115 if(level_samples) delete [] level_samples;
116 calculate_history_size();
117 level_samples = new int64_t[total_peaks];
119 for(int i = 0; i < MAXCHANNELS;i++)
121 current_level[i] = 0;
122 if(buffer[i] && !level_history[i])
123 level_history[i] = new double[total_peaks];
126 for(int i = 0; i < total_peaks; i++)
128 level_samples[i] = -1;
131 for(int j = 0; j < MAXCHANNELS; j++)
134 for(int i = 0; i < total_peaks; i++)
135 level_history[j][i] = 0;
140 void ARender::allocate_buffers(int samples)
142 for(int i = 0; i < MAXCHANNELS; i++)
144 // Reset the output buffers in case speed changed
145 if(buffer_allocated[i] < samples)
151 if(i < renderengine->get_edl()->session->audio_channels)
153 buffer[i] = new Samples(samples);
154 buffer_allocated[i] = samples;
155 audio_out[i] = buffer[i];
160 void ARender::init_output_buffers()
162 allocate_buffers(renderengine->adjusted_fragment_len);
166 VirtualConsole* ARender::new_vconsole_object()
168 return new VirtualAConsole(renderengine, this);
171 int64_t ARender::tounits(double position, int round)
174 return Units::round(position * renderengine->get_edl()->session->sample_rate);
176 return (int64_t)(position * renderengine->get_edl()->session->sample_rate);
179 double ARender::fromunits(int64_t position)
181 return (double)position / renderengine->get_edl()->session->sample_rate;
185 int ARender::process_buffer(Samples **buffer_out,
187 int64_t input_position)
191 int64_t fragment_position = 0;
192 int64_t fragment_len = input_len;
194 current_position = input_position;
196 // Process in fragments
197 int start_offset = buffer_out[0]->get_offset();
198 while(fragment_position < input_len)
200 // Set pointers for destination data
201 for(int i = 0; i < MAXCHANNELS; i++)
205 this->audio_out[i] = buffer_out[i];
206 this->audio_out[i]->set_offset(start_offset + fragment_position);
209 this->audio_out[i] = 0;
212 fragment_len = input_len;
213 if(fragment_position + fragment_len > input_len)
214 fragment_len = input_len - fragment_position;
216 reconfigure = vconsole->test_reconfigure(input_position,
219 //printf("ARender::process_buffer 1 %jd %d\n", input_position, reconfigure);
221 if(reconfigure) restart_playback();
223 result = process_buffer(fragment_len, input_position);
225 fragment_position += fragment_len;
226 input_position += fragment_len;
227 current_position = input_position;
231 for(int i = 0; i < MAXCHANNELS; i++)
233 if(buffer_out[i]) buffer_out[i]->set_offset(start_offset);
242 int ARender::process_buffer(int64_t input_len, int64_t input_position)
244 int result = ((VirtualAConsole*)vconsole)->process_buffer(input_len,
249 int ARender::get_history_number(int64_t *table, int64_t position)
251 // Get the entry closest to position
253 int64_t min_difference = 0x7fffffff;
254 for(int i = 0; i < total_peaks; i++)
257 //printf("%jd ", table[i]);
258 if(labs(table[i] - position) < min_difference)
260 min_difference = labs(table[i] - position);
265 //printf("ARender::get_history_number %jd %d\n", position, result);
269 void ARender::send_last_buffer()
271 if( renderengine->audio )
272 renderengine->audio->set_last_buffer();
275 int ARender::stop_audio(int wait)
277 if( renderengine->audio )
278 renderengine->audio->stop_audio(wait);
282 void ARender::interrupt_playback()
284 //printf("ARender::interrupt_playback\n");
286 if( renderengine->audio )
287 renderengine->audio->interrupt_playback();
292 int64_t current_input_length;
298 start_lock->unlock();
299 if(debug) printf("ARender::run %d %d\n", __LINE__, Thread::calculate_realtime());
301 while(!done && !interrupt)
303 float speed = renderengine->command->get_speed();
304 current_input_length = (int64_t)(renderengine->fragment_len * speed +0.5) ;
306 if(debug) printf("ARender::run %d %jd %jd\n", __LINE__, current_position, current_input_length);
307 get_boundaries(current_input_length);
309 if(debug) printf("ARender::run %d %jd %jd\n", __LINE__, current_position, current_input_length);
310 if(current_input_length)
312 reconfigure = vconsole->test_reconfigure(current_position,
313 current_input_length);
314 if(reconfigure) restart_playback();
316 if(debug) printf("ARender::run %d %jd %jd\n", __LINE__, current_position, current_input_length);
319 // Update tracking if no video is playing.
320 if(renderengine->command->realtime &&
321 renderengine->playback_engine &&
322 !renderengine->do_video)
324 double position = (double)renderengine->audio->current_position() /
325 renderengine->get_edl()->session->sample_rate * speed;
327 if(renderengine->command->get_direction() == PLAY_FORWARD)
328 position += renderengine->command->playbackstart;
330 position = renderengine->command->playbackstart - 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);
338 if(debug) printf("ARender::run %d %jd\n", __LINE__, current_input_length);
342 process_buffer(current_input_length, current_position);
343 if(debug) printf("ARender::run %d\n", __LINE__);
346 advance_position(current_input_length);
347 if(debug) printf("ARender::run %d\n", __LINE__);
350 if(vconsole->interrupt) interrupt = 1;
353 if(debug) printf("ARender::run %d\n", __LINE__);
354 if(!interrupt) send_last_buffer();
355 if(renderengine->command->realtime)
356 stop_audio(interrupt ? 0 : 1);
357 vconsole->stop_rendering(0);
362 int ARender::get_next_peak(int current_peak)
365 if(current_peak >= total_peaks) current_peak = 0;