clear group_id on move_edits, neoph about_bg leak, use inv clr on edit title bar...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / fileflac.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "FLAC/stream_decoder.h"
28 #include "FLAC/stream_encoder.h"
29
30 #define IS_FILEFLAC
31 #include "asset.h"
32 #include "bcsignals.h"
33 #include "bitspopup.h"
34 #include "byteorder.h"
35 #include "clip.h"
36 #include "file.h"
37 #include "fileflac.h"
38 #include "filesystem.h"
39 #include "guicast.h"
40 #include "language.h"
41 #include "mwindow.inc"
42
43
44 FileFLAC::FileFLAC(Asset *asset, File *file)
45  : FileBase(asset, file)
46 {
47         reset_parameters();
48         if(asset->format == FILE_UNKNOWN) asset->format = FILE_FLAC;
49         asset->byte_order = 0;
50 }
51
52 FileFLAC::~FileFLAC()
53 {
54         close_file();
55 }
56
57 void FileFLAC::get_parameters(BC_WindowBase *parent_window,
58         Asset *asset, BC_WindowBase* &format_window,
59         int audio_options, int video_options, EDL *edl)
60 {
61         if(audio_options)
62         {
63                 FLACConfigAudio *window = new FLACConfigAudio(parent_window, asset);
64                 format_window = window;
65                 window->create_objects();
66                 window->run_window();
67                 delete window;
68         }
69 }
70
71
72
73 int FileFLAC::check_sig(Asset *asset, char *test)
74 {
75         if(test[0] == 'f' &&
76                 test[1] == 'L' &&
77                 test[2] == 'a' &&
78                 test[3] == 'C')
79         {
80                 return 1;
81         }
82         else
83         {
84                 return 0;
85         }
86 }
87
88 int FileFLAC::reset_parameters_derived()
89 {
90         pcm_history = 0;
91         flac_decode = 0;
92         flac_encode = 0;
93         temp_buffer = 0;
94         temp_allocated = 0;
95         temp_channels = 0;
96         initialized = 0;
97         is_reading = 0;
98         return 0;
99 }
100
101
102 static FLAC__StreamDecoderWriteStatus write_callback(
103         const FLAC__StreamDecoder *decoder,
104         const FLAC__Frame *frame,
105         const FLAC__int32 * const buffer[],
106         void *client_data)
107 {
108         FileFLAC *ptr = (FileFLAC*)client_data;
109
110         if(!ptr->initialized)
111         {
112                 ptr->initialized = 1;
113                 ptr->asset->audio_data = 1;
114                 ptr->asset->channels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
115                 ptr->asset->bits = FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode);
116                 ptr->asset->sample_rate = FLAC__stream_decoder_get_sample_rate(ptr->flac_decode);
117                 ptr->asset->audio_length = FLAC__stream_decoder_get_total_samples(ptr->flac_decode);
118                 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
119         }
120         else
121         if(ptr->is_reading)
122         {
123                 int fragment = FLAC__stream_decoder_get_blocksize(ptr->flac_decode);
124                 ptr->samples_read += fragment;
125 //printf("write_callback 2 %d\n", fragment);
126
127                 if(ptr->temp_allocated < fragment)
128                 {
129                         if(ptr->temp_buffer)
130                         {
131                                 for(int i = 0; i < ptr->temp_channels; i++)
132                                 {
133                                         delete [] ptr->temp_buffer[i];
134                                 }
135                                 delete [] ptr->temp_buffer;
136                         }
137
138                         ptr->temp_channels = ptr->asset->channels;
139                         ptr->temp_buffer = new int32_t*[ptr->temp_channels];
140                         for(int i = 0; i < ptr->temp_channels; i++)
141                         {
142                                 ptr->temp_buffer[i] = new int32_t[fragment];
143                         }
144                         ptr->temp_allocated = fragment;
145                 }
146
147                 float audio_max = (float)0x7fff;
148                 if(FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode) == 24)
149                         audio_max = (float)0x7fffff;
150
151                 int nchannels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
152                 if( nchannels > ptr->temp_channels ) nchannels = ptr->temp_channels;
153                 for(int j = 0; j < nchannels; j++)
154                 {
155                         float *dst = (float*)ptr->temp_buffer[j];
156                         int32_t *src = (int32_t*)buffer[j];
157                         for(int i = 0; i < fragment; i++)
158                         {
159                                 *dst++ = (float)*src++ / audio_max;
160                         }
161                 }
162
163                 ptr->append_history((float**)ptr->temp_buffer, fragment);
164
165 //printf("write_callback 3\n");
166                 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
167         }
168
169         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
170 }
171
172
173 static void metadata_callback(const FLAC__StreamDecoder *decoder,
174         const FLAC__StreamMetadata *metadata,
175         void *client_data)
176 {
177 //      printf("metadata_callback\n");
178 }
179
180 static void error_callback(const FLAC__StreamDecoder *decoder,
181         FLAC__StreamDecoderErrorStatus status,
182         void *client_data)
183 {
184 //      printf("error_callback\n");
185 }
186
187
188
189
190
191 int FileFLAC::open_file(int rd, int wr)
192 {
193         int result = 0;
194
195         if(rd)
196         {
197                 file_bytes = FileSystem::get_size(asset->path);
198                 flac_decode = FLAC__stream_decoder_new();
199                 FLAC__stream_decoder_init_file(flac_decode,
200                         asset->path,
201                         write_callback,
202                         metadata_callback,
203                         error_callback,
204                         this);
205
206                 initialized = 0;
207                 while(!initialized)
208                 {
209                         if(!FLAC__stream_decoder_process_single(flac_decode)) break;
210                 }
211
212                 if(!initialized)
213                         result = 1;
214                 else
215                 {
216                         FLAC__stream_decoder_seek_absolute(flac_decode, 0);
217                 }
218         }
219
220         if(wr)
221         {
222                 flac_encode = FLAC__stream_encoder_new();
223                 FLAC__stream_encoder_set_channels(flac_encode, asset->channels);
224                 FLAC__stream_encoder_set_bits_per_sample(flac_encode, asset->bits);
225                 FLAC__stream_encoder_set_sample_rate(flac_encode, asset->sample_rate);
226                 FLAC__stream_encoder_init_file(flac_encode,
227                         asset->path,
228                         0,
229                         0);
230         }
231
232         return result;
233 }
234
235
236 int FileFLAC::close_file_derived()
237 {
238         if(flac_decode)
239         {
240                 FLAC__stream_decoder_finish(flac_decode);
241                 FLAC__stream_decoder_delete(flac_decode);
242         }
243
244         if(flac_encode)
245         {
246                 FLAC__stream_encoder_finish(flac_encode);
247                 FLAC__stream_encoder_delete(flac_encode);
248         }
249
250
251         if(temp_buffer)
252         {
253                 for(int i = 0; i < temp_channels; i++)
254                         delete [] temp_buffer[i];
255                 delete [] temp_buffer;
256         }
257         return 0;
258 }
259
260
261 int FileFLAC::write_samples(double **buffer, int64_t len)
262 {
263 // Create temporary buffer of samples
264         if(temp_allocated < len)
265         {
266                 if(temp_buffer)
267                 {
268                         for(int i = 0; i < asset->channels; i++)
269                         {
270                                 delete [] temp_buffer[i];
271                         }
272                         delete [] temp_buffer;
273                 }
274
275                 temp_buffer = new int32_t*[asset->channels];
276                 for(int i = 0; i < asset->channels; i++)
277                 {
278                         temp_buffer[i] = new int32_t[len];
279                 }
280                 temp_allocated = len;
281         }
282
283         float audio_max = (float)0x7fff;
284
285         switch(asset->bits)
286         {
287                 case 24:
288                         audio_max = (float)0x7fffff;
289                         break;
290         }
291
292         for(int i = 0; i < asset->channels; i++)
293         {
294                 int32_t *dst = temp_buffer[i];
295                 double *src = buffer[i];
296                 for(int j = 0; j < len; j++)
297                 {
298                         double sample = *src++ * audio_max;
299                         CLAMP(sample, -audio_max, audio_max);
300                         *dst++ = (int32_t)sample;
301                 }
302         }
303
304         int result = FLAC__stream_encoder_process(flac_encode,
305                 temp_buffer,
306                 len);
307
308         return !result;
309 }
310
311 int FileFLAC::read_samples(double *buffer, int64_t len)
312 {
313         int result = 0;
314         update_pcm_history(len);
315
316         if(decode_end != decode_start)
317         {
318                 FLAC__stream_decoder_seek_absolute(flac_decode, decode_start);
319                 decode_end = decode_start;
320         }
321
322         samples_read = 0;
323         is_reading = 1;
324
325         while(samples_read < decode_len)
326         {
327                 FLAC__uint64 position;
328                 FLAC__stream_decoder_get_decode_position(flac_decode, &position);
329 // EOF
330                 if((int64_t)position >= file_bytes) break;
331                 if(!FLAC__stream_decoder_process_single(flac_decode)) {
332                         result = 1;
333                         break;
334                 }
335         }
336         is_reading = 0;
337
338         if(!result)
339         {
340                 read_history(buffer,
341                         file->current_sample,
342                         file->current_channel,
343                         len);
344         }
345
346 //printf("FileFLAC::read_samples 10\n");
347         return result;
348 }
349
350
351
352
353
354
355
356
357
358
359 FLACConfigAudio::FLACConfigAudio(BC_WindowBase *parent_window,
360         Asset *asset)
361  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
362         parent_window->get_abs_cursor_x(1),
363         parent_window->get_abs_cursor_y(1),
364         350,
365         170,
366         -1,
367         -1,
368         0,
369         0,
370         1)
371 {
372         this->parent_window = parent_window;
373         this->asset = asset;
374 }
375
376 FLACConfigAudio::~FLACConfigAudio()
377 {
378 }
379
380 void FLACConfigAudio::create_objects()
381 {
382         int x = 10, y = 10;
383         lock_window("FLACConfigAudio::create_objects");
384         bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
385         bits_popup->create_objects();
386
387         add_subwindow(new BC_OKButton(this));
388         show_window(1);
389         unlock_window();
390 }
391
392 int FLACConfigAudio::close_event()
393 {
394         set_done(0);
395         return 1;
396 }
397