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 "FLAC/stream_decoder.h"
28 #include "FLAC/stream_encoder.h"
32 #include "bcsignals.h"
33 #include "bitspopup.h"
34 #include "byteorder.h"
38 #include "filesystem.h"
41 #include "mwindow.inc"
44 FileFLAC::FileFLAC(Asset *asset, File *file)
45 : FileBase(asset, file)
48 if(asset->format == FILE_UNKNOWN) asset->format = FILE_FLAC;
49 asset->byte_order = 0;
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)
63 FLACConfigAudio *window = new FLACConfigAudio(parent_window, asset);
64 format_window = window;
65 window->create_objects();
73 int FileFLAC::check_sig(Asset *asset, char *test)
75 return test[0]=='f' && test[1]=='L' && test[2]=='a' && test[3]=='C' ? 1 : 0;
78 int FileFLAC::reset_parameters_derived()
92 static FLAC__StreamDecoderWriteStatus write_callback(
93 const FLAC__StreamDecoder *decoder,
94 const FLAC__Frame *frame,
95 const FLAC__int32 * const buffer[],
98 FileFLAC *ptr = (FileFLAC*)client_data;
100 if(!ptr->initialized)
102 ptr->initialized = 1;
103 ptr->asset->audio_data = 1;
104 ptr->asset->channels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
105 ptr->asset->bits = FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode);
106 ptr->asset->sample_rate = FLAC__stream_decoder_get_sample_rate(ptr->flac_decode);
107 ptr->asset->audio_length = FLAC__stream_decoder_get_total_samples(ptr->flac_decode);
108 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
113 int fragment = FLAC__stream_decoder_get_blocksize(ptr->flac_decode);
114 ptr->samples_read += fragment;
115 //printf("write_callback 2 %d\n", fragment);
117 if(ptr->temp_allocated < fragment)
121 for(int i = 0; i < ptr->temp_channels; i++)
123 delete [] ptr->temp_buffer[i];
125 delete [] ptr->temp_buffer;
128 ptr->temp_channels = ptr->asset->channels;
129 ptr->temp_buffer = new int32_t*[ptr->temp_channels];
130 for(int i = 0; i < ptr->temp_channels; i++)
132 ptr->temp_buffer[i] = new int32_t[fragment];
134 ptr->temp_allocated = fragment;
137 float audio_max = (float)0x7fff;
138 if(FLAC__stream_decoder_get_bits_per_sample(ptr->flac_decode) == 24)
139 audio_max = (float)0x7fffff;
141 int nchannels = FLAC__stream_decoder_get_channels(ptr->flac_decode);
142 if( nchannels > ptr->temp_channels ) nchannels = ptr->temp_channels;
143 for(int j = 0; j < nchannels; j++)
145 float *dst = (float*)ptr->temp_buffer[j];
146 int32_t *src = (int32_t*)buffer[j];
147 for(int i = 0; i < fragment; i++)
149 *dst++ = (float)*src++ / audio_max;
153 ptr->append_history((float**)ptr->temp_buffer, fragment);
155 //printf("write_callback 3\n");
156 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
159 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
163 static void metadata_callback(const FLAC__StreamDecoder *decoder,
164 const FLAC__StreamMetadata *metadata,
167 // printf("metadata_callback\n");
170 static void error_callback(const FLAC__StreamDecoder *decoder,
171 FLAC__StreamDecoderErrorStatus status,
174 // printf("error_callback\n");
181 int FileFLAC::open_file(int rd, int wr)
187 file_bytes = FileSystem::get_size(asset->path);
188 flac_decode = FLAC__stream_decoder_new();
189 FLAC__stream_decoder_init_file(flac_decode,
199 if(!FLAC__stream_decoder_process_single(flac_decode)) break;
206 FLAC__stream_decoder_seek_absolute(flac_decode, 0);
212 flac_encode = FLAC__stream_encoder_new();
213 FLAC__stream_encoder_set_channels(flac_encode, asset->channels);
214 FLAC__stream_encoder_set_bits_per_sample(flac_encode, asset->bits);
215 FLAC__stream_encoder_set_sample_rate(flac_encode, asset->sample_rate);
216 FLAC__stream_encoder_set_compression_level(flac_encode, asset->flac_compression);
217 FLAC__stream_encoder_init_file(flac_encode, asset->path, 0, 0);
224 int FileFLAC::close_file_derived()
228 FLAC__stream_decoder_finish(flac_decode);
229 FLAC__stream_decoder_delete(flac_decode);
234 FLAC__stream_encoder_finish(flac_encode);
235 FLAC__stream_encoder_delete(flac_encode);
241 for(int i = 0; i < temp_channels; i++)
242 delete [] temp_buffer[i];
243 delete [] temp_buffer;
249 int FileFLAC::write_samples(double **buffer, int64_t len)
251 // Create temporary buffer of samples
252 if(temp_allocated < len)
256 for(int i = 0; i < asset->channels; i++)
258 delete [] temp_buffer[i];
260 delete [] temp_buffer;
263 temp_buffer = new int32_t*[asset->channels];
264 for(int i = 0; i < asset->channels; i++)
266 temp_buffer[i] = new int32_t[len];
268 temp_allocated = len;
271 float audio_max = (float)0x7fff;
276 audio_max = (float)0x7fffff;
280 for(int i = 0; i < asset->channels; i++)
282 int32_t *dst = temp_buffer[i];
283 double *src = buffer[i];
284 for(int j = 0; j < len; j++)
286 double sample = *src++ * audio_max;
287 CLAMP(sample, -audio_max, audio_max);
288 *dst++ = (int32_t)sample;
292 int result = FLAC__stream_encoder_process(flac_encode,
299 int FileFLAC::read_samples(double *buffer, int64_t len)
302 update_pcm_history(len);
304 if(decode_end != decode_start)
306 FLAC__stream_decoder_seek_absolute(flac_decode, decode_start);
307 decode_end = decode_start;
313 while(samples_read < decode_len)
315 FLAC__uint64 position;
316 FLAC__stream_decoder_get_decode_position(flac_decode, &position);
318 if((int64_t)position >= file_bytes) break;
319 if(!FLAC__stream_decoder_process_single(flac_decode)) {
329 file->current_sample,
330 file->current_channel,
334 //printf("FileFLAC::read_samples 10\n");
339 FLACConfigAudio::FLACConfigAudio(BC_WindowBase *parent_window,
341 : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
342 parent_window->get_abs_cursor_x(1), parent_window->get_abs_cursor_y(1),
343 xS(350), yS(170), -1, -1, 0, 0, 1)
345 this->parent_window = parent_window;
348 // *** CONTEXT_HELP ***
349 context_help_set_keyword("Single File Rendering");
352 FLACConfigAudio::~FLACConfigAudio()
357 void FLACConfigAudio::create_objects()
360 int ys5 = yS(5), xs100 = xS(100);
361 int x = xS(10), y = yS(10);
362 lock_window("FLACConfigAudio::create_objects");
363 bits_popup = new BitsPopup(this, x, y, &asset->bits, 0, 0, 0, 0, 0);
364 bits_popup->create_objects();
365 y += bits_popup->get_h() + ys5;
366 add_subwindow(title = new BC_Title(x,y,_("Compression:")));
367 int x1 = x + title->get_w() + xs100;
368 compression = new FLACCompression(this, x1, y);
369 compression->create_objects();
370 y += compression->get_h() + ys5;
371 add_subwindow(new BC_OKButton(this));
376 FLACCompression::FLACCompression(FLACConfigAudio *gui, int x, int y)
377 : BC_TumbleTextBox(gui, (int64_t)gui->asset->flac_compression,
378 (int64_t)0, (int64_t)8, x, y, xS(40))
384 int FLACCompression::handle_event()
386 gui->asset->flac_compression = atol(get_text());
391 int FLACConfigAudio::close_event()