r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / filevorbis.C
blob4e4f68068b0a592f154a72ad16a0bc7347c927a6
1 #include "asset.h"
2 #include "byteorder.h"
3 #include "clip.h"
4 #include "file.h"
5 #include "filevorbis.h"
6 #include "guicast.h"
7 #include "language.h"
8 #include "mwindow.inc"
10 #include <errno.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
15 FileVorbis::FileVorbis(Asset *asset, File *file)
16  : FileBase(asset, file)
18         reset_parameters();
19         if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS;
20         asset->byte_order = 0;
23 FileVorbis::~FileVorbis()
25         close_file();
28 void FileVorbis::get_parameters(BC_WindowBase *parent_window, 
29         Asset *asset, 
30         BC_WindowBase* &format_window,
31         int audio_options,
32         int video_options)
34         if(audio_options)
35         {
36                 VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset);
37                 format_window = window;
38                 window->create_objects();
39                 window->run_window();
40                 delete window;
41         }
44 int FileVorbis::check_sig(Asset *asset)
46 // FILEVORBIS DECODING IS DISABLED
47         return 0;
48         FILE *fd = fopen(asset->path, "rb");
49         OggVorbis_File vf;
51 // Test for Quicktime since OGG misinterprets it
52         fseek(fd, 4, SEEK_SET);
53         char data[4];
54         fread(data, 4, 1, fd);
55         if(data[0] == 'm' &&
56                 data[1] == 'd' &&
57                 data[2] == 'a' &&
58                 data[3] == 't')
59         {
60                 fclose(fd);
61                 return 0;
62         }
63         
64         fseek(fd, 0, SEEK_SET);
66         if(ov_open(fd, &vf, NULL, 0) < 0)
67         {
68 // OGG failed.  Close file handle manually.
69                 ov_clear(&vf);
70                 if(fd) fclose(fd);
71                 return 0;
72         }
73         else
74         {
75                 ov_clear(&vf);
76                 return 1;
77         }
80 int FileVorbis::reset_parameters_derived()
82         fd = 0;
83         bzero(&vf, sizeof(vf));
84         pcm_history = 0;
85         pcm_history_float = 0;
89 // Just create the Quicktime objects since this routine is also called
90 // for reopening.
91 int FileVorbis::open_file(int rd, int wr)
93         int result = 0;
94         this->rd = rd;
95         this->wr = wr;
97 //printf("FileVorbis::open_file 1\n");
98         if(rd)
99         {
100 //printf("FileVorbis::open_file 1\n");
101                 if(!(fd = fopen(asset->path, "rb")))
102                 {
103                         printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
104                         result = 1;
105                 }
106                 else
107                 {
108 //printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
109                         if(ov_open(fd, &vf, NULL, 0) < 0)
110                         {
111                                 printf(_("FileVorbis::open_file %s: invalid bitstream.\n"), asset->path);
112                                 result = 1;
113                         }
114                         else
115                         {
116 //printf("FileVorbis::open_file 1\n");
117                                 vorbis_info *vi = ov_info(&vf, -1);
118                                 asset->channels = vi->channels;
119                                 if(!asset->sample_rate)
120                                         asset->sample_rate = vi->rate;
121 //printf("FileVorbis::open_file 1\n");
122                                 asset->audio_length = ov_pcm_total(&vf,-1);
123 //printf("FileVorbis::open_file 1\n");
124                                 asset->audio_data = 1;
125 // printf("FileVorbis::open_file 1 %d %d %d\n", 
126 // asset->channels, 
127 // asset->sample_rate, 
128 // asset->audio_length);
129                         }
130                 }
131         }
133         if(wr)
134         {
135                 if(!(fd = fopen(asset->path, "wb")))
136                 {
137                         printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
138                         result = 1;
139                 }
140                 else
141                 {
142                         vorbis_info_init(&vi);
143                         if(!asset->vorbis_vbr)
144                                 result = vorbis_encode_init(&vi, 
145                                         asset->channels, 
146                                         asset->sample_rate, 
147                                         asset->vorbis_max_bitrate, 
148                                         asset->vorbis_bitrate, 
149                                         asset->vorbis_min_bitrate);
150                         else
151                         {
152                                 result = vorbis_encode_setup_managed(&vi,
153                                         asset->channels, 
154                                         asset->sample_rate, 
155                                         asset->vorbis_max_bitrate, 
156                                         asset->vorbis_bitrate, 
157                                         asset->vorbis_min_bitrate);
158                                 result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
159                                 result |= vorbis_encode_setup_init(&vi);
160                         }
162                         if(!result)
163                         {
164                                 vorbis_analysis_init(&vd, &vi);
165                                 vorbis_block_init(&vd, &vb);
166                                 vorbis_comment_init(&vc);
167                                 srand(time(NULL));
168                                 ogg_stream_init(&os, rand());
170                                 ogg_packet header;
171                                 ogg_packet header_comm;
172                                 ogg_packet header_code;
173                                 vorbis_analysis_headerout(&vd, 
174                                         &vc,
175                                         &header,
176                                         &header_comm,
177                                         &header_code);
178                                 ogg_stream_packetin(&os,
179                                         &header);
180                                 ogg_stream_packetin(&os, 
181                                         &header_comm);
182                                 ogg_stream_packetin(&os,
183                                         &header_code);
185                                 while(1)
186                                 {
187                                         int result = ogg_stream_flush(&os, &og);
188                                         if(result == 0) break;
189                                         fwrite(og.header, 1, og.header_len, fd);
190                                         fwrite(og.body, 1, og.body_len, fd);
191                                 }
192                         }
193                 }
194         }
196 //printf("FileVorbis::open_file 2\n");
197         return result;
200 #define FLUSH_VORBIS \
201 while(vorbis_analysis_blockout(&vd, &vb) == 1) \
202 { \
203         vorbis_analysis(&vb, NULL); \
204         vorbis_bitrate_addblock(&vb); \
205         while(vorbis_bitrate_flushpacket(&vd, &op)) \
206         { \
207                 ogg_stream_packetin(&os, &op); \
208                 int done = 0; \
209                 while(1) \
210                 { \
211                         int result = ogg_stream_pageout(&os, &og); \
212                         if(!result) break; \
213                         fwrite(og.header, 1, og.header_len, fd); \
214                         fwrite(og.body, 1, og.body_len, fd); \
215                         if(ogg_page_eos(&og)) break; \
216                 } \
217         } \
221 int FileVorbis::close_file()
223         if(fd)
224         {
225                 if(wr)
226                 {
227                         vorbis_analysis_wrote(&vd, 0);
228                         FLUSH_VORBIS
230                         ogg_stream_clear(&os);
231                         vorbis_block_clear(&vb);
232                         vorbis_dsp_clear(&vd);
233                         vorbis_comment_clear(&vc);
234                         vorbis_info_clear(&vi);
235                         fclose(fd);
236                 }
237                 
238                 if(rd)
239                 {
240 // This also closes the file handle.
241                         ov_clear(&vf);
242                 }
243                 fd = 0;
244         }
246         if(pcm_history)
247         {
248                 for(int i = 0; i < asset->channels; i++)
249                         delete [] pcm_history[i];
250                 delete [] pcm_history;
251         }
252         if(pcm_history_float)
253         {
254                 for(int i = 0; i < asset->channels; i++)
255                         delete [] pcm_history_float[i];
256                 delete [] pcm_history_float;
257         }
259         reset_parameters();
260         FileBase::close_file();
261         return 0;
265 int FileVorbis::write_samples(double **buffer, int64_t len)
267         if(!fd) return 0;
268         int result = 0;
270         float **vorbis_buffer = vorbis_analysis_buffer(&vd, len);
271         for(int i = 0; i < asset->channels; i++)
272         {
273                 float *output = vorbis_buffer[i];
274                 double *input = buffer[i];
275                 for(int j = 0; j < len; j++)
276                 {
277                         output[j] = input[j];
278                 }
279         }
280     vorbis_analysis_wrote(&vd, len);
282         FLUSH_VORBIS
284         return result;
287 int FileVorbis::read_samples(double *buffer, int64_t len)
289         if(!fd) return 0;
291 // printf("FileVorbis::read_samples 1 %d %d %d %d\n", 
292 // history_start, 
293 // history_size,
294 // file->current_sample,
295 // len);
296         float **vorbis_output;
297         int bitstream;
298         int accumulation = 0;
299 //printf("FileVorbis::read_samples 1\n");
300         int decode_start = 0;
301         int decode_len = 0;
303         if(len > 0x100000)
304         {
305                 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
306                 return 1;
307         }
309         if(!pcm_history)
310         {
311                 pcm_history = new double*[asset->channels];
312                 for(int i = 0; i < asset->channels; i++)
313                         pcm_history[i] = new double[HISTORY_MAX];
314                 history_start = 0;
315                 history_size = 0;
316         }
318 // Restart history.  Don't bother shifting history back.
319         if(file->current_sample < history_start ||
320                 file->current_sample > history_start + history_size)
321         {
322                 history_size = 0;
323                 history_start = file->current_sample;
324                 decode_start = file->current_sample;
325                 decode_len = len;
326         }
327         else
328 // Shift history forward to make room for new samples
329         if(file->current_sample + len > history_start + history_size)
330         {
331                 if(file->current_sample + len > history_start + HISTORY_MAX)
332                 {
333                         int diff = file->current_sample + len - (history_start + HISTORY_MAX);
334                         for(int i = 0; i < asset->channels; i++)
335                         {
336                                 double *temp = pcm_history[i];
337                                 for(int j = 0; j < HISTORY_MAX - diff; j++)
338                                 {
339                                         temp[j] = temp[j + diff];
340                                 }
341                         }
342                         history_start += diff;
343                         history_size -= diff;
344                 }
346 // Decode more data
347                 decode_start = history_start + history_size;
348                 decode_len = file->current_sample + len - (history_start + history_size);
349         }
352 // Fill history buffer
353         if(history_start + history_size != ov_pcm_tell(&vf))
354         {
355 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
356                 ov_pcm_seek(&vf, history_start + history_size);
357         }
359         while(accumulation < decode_len)
360         {
361                 int result = ov_read_float(&vf,
362                         &vorbis_output,
363                         decode_len - accumulation,
364                         &bitstream);
365 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
366                 if(!result) break;
368                 for(int i = 0; i < asset->channels; i++)
369                 {
370                         double *output = pcm_history[i] + history_size;
371                         float *input = vorbis_output[i];
372                         for(int j = 0; j < result; j++)
373                                 output[j] = input[j];
374                 }
375                 history_size += result;
376                 accumulation += result;
377         }
380 // printf("FileVorbis::read_samples 1 %d %d\n", 
381 // file->current_sample,
382 // history_start);
384         double *input = pcm_history[file->current_channel] + 
385                 file->current_sample - 
386                 history_start;
387         for(int i = 0; i < len; i++)
388                 buffer[i] = input[i];
390 // printf("FileVorbis::read_samples 2 %d %d %d %d\n", 
391 // history_start, 
392 // history_size,
393 // file->current_sample,
394 // len);
396         return 0;
399 int FileVorbis::prefer_samples_float() 
401         return 1;
404 int FileVorbis::read_samples_float(float *buffer, int64_t len)
406         if(!fd) return 0;
408 // printf("FileVorbis::read_samples 1 %d %d %d %d\n", 
409 // history_start, 
410 // history_size,
411 // file->current_sample,
412 // len);
413         float **vorbis_output;
414         int bitstream;
415         int accumulation = 0;
416 //printf("FileVorbis::read_samples 1\n");
417         int decode_start = 0;
418         int decode_len = 0;
420         if(len > 0x100000)
421         {
422                 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
423                 return 1;
424         }
426         if(!pcm_history_float)
427         {
428                 pcm_history_float = new float*[asset->channels];
429                 for(int i = 0; i < asset->channels; i++)
430                         pcm_history_float[i] = new float[HISTORY_MAX];
431                 history_start = 0;
432                 history_size = 0;
433         }
435 // Restart history.  Don't bother shifting history back.
436         if(file->current_sample < history_start ||
437                 file->current_sample > history_start + history_size)
438         {
439                 history_size = 0;
440                 history_start = file->current_sample;
441                 decode_start = file->current_sample;
442                 decode_len = len;
443         }
444         else
445 // Shift history forward to make room for new samples
446         if(file->current_sample + len > history_start + history_size)
447         {
448                 if(file->current_sample + len > history_start + HISTORY_MAX)
449                 {
450                         int diff = file->current_sample + len - (history_start + HISTORY_MAX);
451                         for(int i = 0; i < asset->channels; i++)
452                         {
453                                 float *temp = pcm_history_float[i];
454 //                              for(int j = 0; j < HISTORY_MAX - diff; j++)
455 //                              {
456 //                                      temp[j] = temp[j + diff];
457 //                              }
458                                 bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float));
459                         }
460                         history_start += diff;
461                         history_size -= diff;
462                 }
464 // Decode more data
465                 decode_start = history_start + history_size;
466                 decode_len = file->current_sample + len - (history_start + history_size);
467         }
470 // Fill history buffer
471         if(history_start + history_size != ov_pcm_tell(&vf))
472         {
473 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
474                 ov_pcm_seek(&vf, history_start + history_size);
475         }
477         while(accumulation < decode_len)
478         {
479                 int result = ov_read_float(&vf,
480                         &vorbis_output,
481                         decode_len - accumulation,
482                         &bitstream);
483 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
484                 if(!result) break;
486                 for(int i = 0; i < asset->channels; i++)
487                 {
488                         float *output = pcm_history_float[i] + history_size;
489                         float *input = vorbis_output[i];
490 //                      for(int j = 0; j < result; j++)
491 //                              output[j] = input[j];
492                         bcopy(input, output, result * sizeof(float));
493                 }
494                 history_size += result;
495                 accumulation += result;
496         }
499 // printf("FileVorbis::read_samples 1 %d %d\n", 
500 // file->current_sample,
501 // history_start);
503         float *input = pcm_history_float[file->current_channel] + 
504                 file->current_sample - 
505                 history_start;
506 //      for(int i = 0; i < len; i++)
507 //              buffer[i] = input[i];
508         bcopy(input, buffer, len * sizeof(float));
510 // printf("FileVorbis::read_samples 2 %d %d %d %d\n", 
511 // history_start, 
512 // history_size,
513 // file->current_sample,
514 // len);
516         return 0;
528 VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window, 
529         Asset *asset)
530  : BC_Window(PROGRAM_NAME ": Audio Compression",
531         parent_window->get_abs_cursor_x(1),
532         parent_window->get_abs_cursor_y(1),
533         350,
534         170,
535         -1,
536         -1,
537         0,
538         0,
539         1)
541         this->parent_window = parent_window;
542         this->asset = asset;
545 VorbisConfigAudio::~VorbisConfigAudio()
549 int VorbisConfigAudio::create_objects()
551         int x = 10, y = 10;
552         int x1 = 150;
553         char string[BCTEXTLEN];
555         add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this));
556         add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this));
558         y += 30;
559         sprintf(string, "%d", asset->vorbis_min_bitrate);
560         add_tool(new BC_Title(x, y, _("Min bitrate:")));
561         add_tool(new VorbisMinBitrate(x1, y, this, string));
563         y += 30;
564         add_tool(new BC_Title(x, y, _("Avg bitrate:")));
565         sprintf(string, "%d", asset->vorbis_bitrate);
566         add_tool(new VorbisAvgBitrate(x1, y, this, string));
568         y += 30;
569         add_tool(new BC_Title(x, y, _("Max bitrate:")));
570         sprintf(string, "%d", asset->vorbis_max_bitrate);
571         add_tool(new VorbisMaxBitrate(x1, y, this, string));
574         add_subwindow(new BC_OKButton(this));
575         show_window();
576         flush();
577         return 0;
580 int VorbisConfigAudio::close_event()
582         set_done(0);
583         return 1;
590 VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui)
591  : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate"))
593         this->gui = gui;
595 int VorbisFixedBitrate::handle_event()
597         gui->asset->vorbis_vbr = 0;
598         gui->variable_bitrate->update(0);
599         return 1;
602 VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui)
603  : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
605         this->gui = gui;
607 int VorbisVariableBitrate::handle_event()
609         gui->asset->vorbis_vbr = 1;
610         gui->fixed_bitrate->update(0);
611         return 1;
615 VorbisMinBitrate::VorbisMinBitrate(int x, 
616         int y, 
617         VorbisConfigAudio *gui, 
618         char *text)
619  : BC_TextBox(x, y, 180, 1, text)
621         this->gui = gui;
623 int VorbisMinBitrate::handle_event()
625         gui->asset->vorbis_min_bitrate = atol(get_text());
626         return 1;
631 VorbisMaxBitrate::VorbisMaxBitrate(int x, 
632         int y, 
633         VorbisConfigAudio *gui,
634         char *text)
635  : BC_TextBox(x, y, 180, 1, text)
637         this->gui = gui;
639 int VorbisMaxBitrate::handle_event()
641         gui->asset->vorbis_max_bitrate = atol(get_text());
642         return 1;
647 VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text)
648  : BC_TextBox(x, y, 180, 1, text)
650         this->gui = gui;
652 int VorbisAvgBitrate::handle_event()
654         gui->asset->vorbis_bitrate = atol(get_text());
655         return 1;