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
23 #include "bcsignals.h"
25 #include "condition.h"
27 #include "edlsession.h"
29 #include "indexfile.h"
30 #include "indexstate.h"
31 #include "indexthread.h"
33 #include "maxchannels.h"
35 #include "mwindowgui.h"
36 #include "preferences.h"
37 #include "mainsession.h"
40 #include "trackcanvas.h"
43 // Read data from buffers and calculate peaks
45 IndexThread::IndexThread(MWindow *mwindow,
46 IndexFile *index_file,
49 int64_t length_source)
52 this->buffer_size = buffer_size;
53 this->length_source = length_source;
54 this->mwindow = mwindow;
55 this->index_filename = index_filename;
56 this->index_file = index_file;
57 IndexState *index_state = index_file->get_state();
59 // initialize output data
60 // size of output file in floats
61 int64_t index_size = mwindow->preferences->index_size /
64 delete [] index_state->index_buffer;
65 delete [] index_state->index_offsets;
66 delete [] index_state->index_sizes;
68 index_state->channels = index_file->source_channels;
69 // buffer used for drawing during the build. This is not deleted in the index_state
70 index_state->index_buffer = new float[index_size];
71 // This is deleted in the index_state's destructor
72 index_state->index_offsets = new int64_t[index_state->channels];
73 index_state->index_sizes = new int64_t[index_state->channels];
74 bzero(index_state->index_buffer, index_size * sizeof(float));
76 // initialization is completed in run
77 for(int i = 0; i < TOTAL_INDEX_BUFFERS; i++)
79 // Must allocate MAX_CHANNELS for a nested EDL
80 int min_channels = MAX(MAX_CHANNELS, index_file->source_channels);
81 buffer_in[i] = new Samples*[min_channels];
82 bzero(buffer_in[i], sizeof(Samples*) * min_channels);
84 output_lock[i] = new Condition(0, "IndexThread::output_lock");
85 input_lock[i] = new Condition(1, "IndexThread::input_lock");
88 for(int j = 0; j < index_file->source_channels; j++)
90 buffer_in[i][j] = new Samples(buffer_size);
94 //printf("IndexThread::IndexThread %d\n", __LINE__);
95 //index_state->dump();
100 IndexThread::~IndexThread()
102 IndexState *index_state = index_file->get_state();
104 for(int i = 0; i < TOTAL_INDEX_BUFFERS; i++)
106 for(int j = 0; j < index_file->source_channels; j++)
108 delete buffer_in[i][j];
110 delete [] buffer_in[i];
111 delete output_lock[i];
112 delete input_lock[i];
115 delete [] index_state->index_buffer;
116 index_state->index_buffer = 0;
119 int IndexThread::start_build()
123 for(int i = 0; i < TOTAL_INDEX_BUFFERS; i++) last_buffer[i] = 0;
128 int IndexThread::stop_build()
134 void IndexThread::run()
138 // current high samples in index
140 // current low samples in the index
142 // position in current indexframe
143 int64_t *frame_position;
145 IndexState *index_state = index_file->get_state();
147 highpoint = new int64_t[index_file->source_channels];
148 lowpoint = new int64_t[index_file->source_channels];
149 frame_position = new int64_t[index_file->source_channels];
151 // predict first highpoint for each channel plus padding and initialize it
152 for(int64_t channel = 0; channel < index_file->source_channels; channel++)
155 index_state->index_offsets[channel] =
156 (length_source / index_state->index_zoom * 2 + 1) * channel;
157 lowpoint[channel] = highpoint[channel] + 1;
159 index_state->index_sizes[channel] = 0;
160 frame_position[channel] = 0;
163 //int64_t index_start = 0; // end of index during last edit update
164 index_state->index_end = 0; // samples in source completed
165 index_state->old_index_end = 0;
166 index_state->index_status = INDEX_BUILDING;
167 int64_t zoomx = index_state->index_zoom;
168 float *index_buffer = index_state->index_buffer; // output of index build
169 int64_t *index_sizes = index_state->index_sizes;
170 int64_t *index_offsets = index_state->index_offsets;
171 //printf("IndexThread::run %d\n", __LINE__);
172 //index_state->dump();
173 //printf("IndexThread::run %d\n", __LINE__);
175 while(!interrupt_flag && !done)
177 output_lock[current_buffer]->lock("IndexThread::run");
179 if(last_buffer[current_buffer]) done = 1;
180 if(!interrupt_flag && !done)
183 int64_t fragment_size = input_len[current_buffer];
185 // printf("IndexThread::run %d index_state->channels=%d index_file->source_channels=%d index_state->index_buffer=%p buffer_in=%p\n",
187 // index_state->channels,
188 // index_file->source_channels,
189 // index_state->index_buffer,
191 for(int channel = 0; channel < index_file->source_channels; channel++)
194 int64_t *highpoint_channel = &highpoint[channel];
195 int64_t *lowpoint_channel = &lowpoint[channel];
196 int64_t *frame_position_channel = &frame_position[channel];
197 double *buffer_source = buffer_in[current_buffer][channel]->get_data();
200 for(int64_t i = 0; i < fragment_size; i++)
202 if(*frame_position_channel == zoomx)
204 *highpoint_channel += 2;
205 *lowpoint_channel += 2;
206 *frame_position_channel = 0;
207 // store and reset output values
208 index_buffer[*highpoint_channel] =
209 index_buffer[*lowpoint_channel] =
211 index_sizes[channel] =
213 index_offsets[channel] +
218 // get high and low points
221 index_buffer[*highpoint_channel] =
222 index_buffer[*lowpoint_channel] = buffer_source[i];
227 if(buffer_source[i] > index_buffer[*highpoint_channel])
228 index_buffer[*highpoint_channel] = buffer_source[i];
230 if(buffer_source[i] < index_buffer[*lowpoint_channel])
231 index_buffer[*lowpoint_channel] = buffer_source[i];
234 (*frame_position_channel)++;
235 } // end index one buffer
239 index_state->index_end += fragment_size;
241 // draw simultaneously with build
242 index_file->redraw_edits(0);
243 //index_start = index_state->index_end;
246 input_lock[current_buffer]->unlock();
248 if(current_buffer >= TOTAL_INDEX_BUFFERS) current_buffer = 0;
251 index_file->redraw_edits(1);
253 // write the index file to disk
254 index_state->write_index(index_filename,
255 (lowpoint[index_file->source_channels - 1] + 1) * sizeof(float),
256 index_file->indexable->is_asset ? (Asset*)index_file->indexable : 0,
257 index_file->source_length);
262 delete [] frame_position;