4 * Copyright (C) 2008 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
27 #include "audiodevice.h"
28 #include "bcsignals.h"
29 #include "condition.h"
33 #include "edlsession.h"
35 #include "levelwindow.h"
36 #include "playabletracks.h"
38 #include "preferences.h"
39 #include "renderengine.h"
43 #include "transportque.h"
44 #include "virtualaconsole.h"
45 #include "virtualanode.h"
46 #include "virtualnode.h"
49 VirtualAConsole::VirtualAConsole(RenderEngine *renderengine, ARender *arender)
50 : VirtualConsole(renderengine, arender, TRACK_AUDIO)
52 this->arender = arender;
54 output_allocation = 0;
57 VirtualAConsole::~VirtualAConsole()
59 if(output_temp) delete output_temp;
63 void VirtualAConsole::get_playable_tracks()
66 playable_tracks = new PlayableTracks(renderengine->get_edl(),
67 commonrender->current_position,
68 renderengine->command->get_direction(),
74 VirtualNode* VirtualAConsole::new_entry_node(Track *track,
78 return new VirtualANode(renderengine,
79 this, module, 0, track, 0);
85 int VirtualAConsole::process_buffer(int64_t len,
86 int64_t start_position)
90 if(debug) printf("VirtualAConsole::process_buffer %d this=%p len=%jd\n",
94 // clear output buffers
95 for(int i = 0; i < MAX_CHANNELS; i++)
97 // if(debug) printf("VirtualAConsole::process_buffer 2 %d %p %jd\n",
99 // arender->audio_out[i],
102 if(arender->audio_out[i])
104 bzero(arender->audio_out[i]->get_data(), len * sizeof(double));
108 // Create temporary output
109 if(output_temp && output_allocation < len)
117 output_temp = new Samples(len);
118 output_allocation = len;
120 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
123 // Reset plugin rendering status
125 //printf("VirtualAConsole::process_buffer 1 %p\n", output_temp);
127 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
131 for(int i = 0; i < exit_nodes.total; i++)
133 VirtualANode *node = (VirtualANode*)exit_nodes.values[i];
134 Track *track = node->track;
136 result |= node->render(output_temp,
138 start_position + track->nudge,
139 renderengine->get_edl()->session->sample_rate);
141 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
145 // get peaks and limit volume in the fragment
146 for(int i = 0; i < MAX_CHANNELS; i++)
148 if(arender->audio_out[i])
150 double *current_buffer = arender->audio_out[i]->get_data();
153 for(int j = 0; j < len; )
155 int meter_render_end;
156 // Get length to test for meter and limit
157 if(renderengine->command->realtime)
158 meter_render_end = j + arender->meter_render_fragment;
160 meter_render_end = len;
162 if(meter_render_end > len)
163 meter_render_end = len;
166 while( j < meter_render_end ) {
167 // Level history comes before clipping to get over status
168 double *sample = ¤t_buffer[j++];
169 if( fabs(*sample) > peak ) peak = fabs(*sample);
170 // Make the output device clip it
171 // if(*sample > 1) *sample = 1;
173 // if(*sample < -1) *sample = -1;
176 if( renderengine->command->realtime ) {
177 int direction = renderengine->command->get_direction();
178 int64_t pos = direction == PLAY_REVERSE ?
181 arender->meter_history->set_peak(i, peak, pos);
187 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
193 // Pack channels, fix speed and send to device.
194 if(!renderengine->is_nested &&
195 renderengine->command->realtime &&
199 float speed = renderengine->command->get_speed();
200 // length compensated for speed
201 int real_output_len = 0;
202 double *audio_out_packed[MAX_CHANNELS];
203 int audio_channels = renderengine->get_edl()->session->audio_channels;
205 for( int i=0; i<audio_channels; ++i )
206 audio_out_packed[i] = arender->audio_out[i]->get_data();
208 // Time stretch the fragment to the real_output size
209 for( int i=0; i<audio_channels; ++i ) {
210 double *current_buffer = audio_out_packed[i];
211 if( speed > 1 ) { // buffer gets shorter
214 int next = (out+1) * speed;
215 if( next > len) next = len;
216 double sample = current_buffer[in];
217 for( int i=in; ++i<next; ) sample += current_buffer[i];
219 if( l > 1 ) sample /= l;
220 current_buffer[out++] = sample;
223 real_output_len = out;
225 else if( speed < 1 ) { // buffer gets longer
226 real_output_len = len / speed;
227 int in = len, out = real_output_len;
228 while( in > 0 && out > 0 ) {
229 double sample = current_buffer[--in];
230 int next = in / speed;
231 while( out > next ) current_buffer[--out] = sample;
235 real_output_len = len;
238 // Wait until video is ready
239 if( arender->first_buffer ) {
240 renderengine->first_frame_lock->lock("VirtualAConsole::process_buffer");
241 arender->first_buffer = 0;
243 if( !renderengine->audio->get_interrupted() ) {
244 renderengine->audio->write_buffer(audio_out_packed, audio_channels,
248 if( renderengine->audio->get_interrupted() )
256 int VirtualAConsole::init_rendering(int duplicate)
262 int VirtualAConsole::send_last_output_buffer()
264 renderengine->audio->set_last_buffer();