5 #include "filevorbis.h"
15 FileVorbis::FileVorbis(Asset *asset, File *file)
16 : FileBase(asset, file)
19 if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS;
20 asset->byte_order = 0;
23 FileVorbis::~FileVorbis()
28 void FileVorbis::get_parameters(BC_WindowBase *parent_window,
30 BC_WindowBase* &format_window,
36 VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset);
37 format_window = window;
38 window->create_objects();
44 int FileVorbis::check_sig(Asset *asset)
46 // FILEVORBIS DECODING IS DISABLED
48 FILE *fd = fopen(asset->path, "rb");
51 // Test for Quicktime since OGG misinterprets it
52 fseek(fd, 4, SEEK_SET);
54 fread(data, 4, 1, fd);
64 fseek(fd, 0, SEEK_SET);
66 if(ov_open(fd, &vf, NULL, 0) < 0)
68 // OGG failed. Close file handle manually.
80 int FileVorbis::reset_parameters_derived()
83 bzero(&vf, sizeof(vf));
85 pcm_history_float = 0;
89 // Just create the Quicktime objects since this routine is also called
91 int FileVorbis::open_file(int rd, int wr)
97 //printf("FileVorbis::open_file 1\n");
100 //printf("FileVorbis::open_file 1\n");
101 if(!(fd = fopen(asset->path, "rb")))
103 printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
108 //printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
109 if(ov_open(fd, &vf, NULL, 0) < 0)
111 printf(_("FileVorbis::open_file %s: invalid bitstream.\n"), asset->path);
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",
127 // asset->sample_rate,
128 // asset->audio_length);
135 if(!(fd = fopen(asset->path, "wb")))
137 printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
142 vorbis_info_init(&vi);
143 if(!asset->vorbis_vbr)
144 result = vorbis_encode_init(&vi,
147 asset->vorbis_max_bitrate,
148 asset->vorbis_bitrate,
149 asset->vorbis_min_bitrate);
152 result = vorbis_encode_setup_managed(&vi,
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);
164 vorbis_analysis_init(&vd, &vi);
165 vorbis_block_init(&vd, &vb);
166 vorbis_comment_init(&vc);
168 ogg_stream_init(&os, rand());
171 ogg_packet header_comm;
172 ogg_packet header_code;
173 vorbis_analysis_headerout(&vd,
178 ogg_stream_packetin(&os,
180 ogg_stream_packetin(&os,
182 ogg_stream_packetin(&os,
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);
196 //printf("FileVorbis::open_file 2\n");
200 #define FLUSH_VORBIS \
201 while(vorbis_analysis_blockout(&vd, &vb) == 1) \
203 vorbis_analysis(&vb, NULL); \
204 vorbis_bitrate_addblock(&vb); \
205 while(vorbis_bitrate_flushpacket(&vd, &op)) \
207 ogg_stream_packetin(&os, &op); \
211 int result = ogg_stream_pageout(&os, &og); \
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; \
221 int FileVorbis::close_file()
227 vorbis_analysis_wrote(&vd, 0);
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);
240 // This also closes the file handle.
248 for(int i = 0; i < asset->channels; i++)
249 delete [] pcm_history[i];
250 delete [] pcm_history;
252 if(pcm_history_float)
254 for(int i = 0; i < asset->channels; i++)
255 delete [] pcm_history_float[i];
256 delete [] pcm_history_float;
260 FileBase::close_file();
265 int FileVorbis::write_samples(double **buffer, int64_t len)
270 float **vorbis_buffer = vorbis_analysis_buffer(&vd, len);
271 for(int i = 0; i < asset->channels; i++)
273 float *output = vorbis_buffer[i];
274 double *input = buffer[i];
275 for(int j = 0; j < len; j++)
277 output[j] = input[j];
280 vorbis_analysis_wrote(&vd, len);
287 int FileVorbis::read_samples(double *buffer, int64_t len)
291 // printf("FileVorbis::read_samples 1 %d %d %d %d\n",
294 // file->current_sample,
296 float **vorbis_output;
298 int accumulation = 0;
299 //printf("FileVorbis::read_samples 1\n");
300 int decode_start = 0;
305 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
311 pcm_history = new double*[asset->channels];
312 for(int i = 0; i < asset->channels; i++)
313 pcm_history[i] = new double[HISTORY_MAX];
318 // Restart history. Don't bother shifting history back.
319 if(file->current_sample < history_start ||
320 file->current_sample > history_start + history_size)
323 history_start = file->current_sample;
324 decode_start = file->current_sample;
328 // Shift history forward to make room for new samples
329 if(file->current_sample + len > history_start + history_size)
331 if(file->current_sample + len > history_start + HISTORY_MAX)
333 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
334 for(int i = 0; i < asset->channels; i++)
336 double *temp = pcm_history[i];
337 for(int j = 0; j < HISTORY_MAX - diff; j++)
339 temp[j] = temp[j + diff];
342 history_start += diff;
343 history_size -= diff;
347 decode_start = history_start + history_size;
348 decode_len = file->current_sample + len - (history_start + history_size);
352 // Fill history buffer
353 if(history_start + history_size != ov_pcm_tell(&vf))
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);
359 while(accumulation < decode_len)
361 int result = ov_read_float(&vf,
363 decode_len - accumulation,
365 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
368 for(int i = 0; i < asset->channels; i++)
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];
375 history_size += result;
376 accumulation += result;
380 // printf("FileVorbis::read_samples 1 %d %d\n",
381 // file->current_sample,
384 double *input = pcm_history[file->current_channel] +
385 file->current_sample -
387 for(int i = 0; i < len; i++)
388 buffer[i] = input[i];
390 // printf("FileVorbis::read_samples 2 %d %d %d %d\n",
393 // file->current_sample,
399 int FileVorbis::prefer_samples_float()
404 int FileVorbis::read_samples_float(float *buffer, int64_t len)
408 // printf("FileVorbis::read_samples 1 %d %d %d %d\n",
411 // file->current_sample,
413 float **vorbis_output;
415 int accumulation = 0;
416 //printf("FileVorbis::read_samples 1\n");
417 int decode_start = 0;
422 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
426 if(!pcm_history_float)
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];
435 // Restart history. Don't bother shifting history back.
436 if(file->current_sample < history_start ||
437 file->current_sample > history_start + history_size)
440 history_start = file->current_sample;
441 decode_start = file->current_sample;
445 // Shift history forward to make room for new samples
446 if(file->current_sample + len > history_start + history_size)
448 if(file->current_sample + len > history_start + HISTORY_MAX)
450 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
451 for(int i = 0; i < asset->channels; i++)
453 float *temp = pcm_history_float[i];
454 // for(int j = 0; j < HISTORY_MAX - diff; j++)
456 // temp[j] = temp[j + diff];
458 bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float));
460 history_start += diff;
461 history_size -= diff;
465 decode_start = history_start + history_size;
466 decode_len = file->current_sample + len - (history_start + history_size);
470 // Fill history buffer
471 if(history_start + history_size != ov_pcm_tell(&vf))
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);
477 while(accumulation < decode_len)
479 int result = ov_read_float(&vf,
481 decode_len - accumulation,
483 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
486 for(int i = 0; i < asset->channels; i++)
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));
494 history_size += result;
495 accumulation += result;
499 // printf("FileVorbis::read_samples 1 %d %d\n",
500 // file->current_sample,
503 float *input = pcm_history_float[file->current_channel] +
504 file->current_sample -
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",
513 // file->current_sample,
528 VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window,
530 : BC_Window(PROGRAM_NAME ": Audio Compression",
531 parent_window->get_abs_cursor_x(1),
532 parent_window->get_abs_cursor_y(1),
541 this->parent_window = parent_window;
545 VorbisConfigAudio::~VorbisConfigAudio()
549 int VorbisConfigAudio::create_objects()
553 char string[BCTEXTLEN];
555 add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this));
556 add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this));
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));
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));
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));
580 int VorbisConfigAudio::close_event()
590 VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui)
591 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate"))
595 int VorbisFixedBitrate::handle_event()
597 gui->asset->vorbis_vbr = 0;
598 gui->variable_bitrate->update(0);
602 VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui)
603 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
607 int VorbisVariableBitrate::handle_event()
609 gui->asset->vorbis_vbr = 1;
610 gui->fixed_bitrate->update(0);
615 VorbisMinBitrate::VorbisMinBitrate(int x,
617 VorbisConfigAudio *gui,
619 : BC_TextBox(x, y, 180, 1, text)
623 int VorbisMinBitrate::handle_event()
625 gui->asset->vorbis_min_bitrate = atol(get_text());
631 VorbisMaxBitrate::VorbisMaxBitrate(int x,
633 VorbisConfigAudio *gui,
635 : BC_TextBox(x, y, 180, 1, text)
639 int VorbisMaxBitrate::handle_event()
641 gui->asset->vorbis_max_bitrate = atol(get_text());
647 VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text)
648 : BC_TextBox(x, y, 180, 1, text)
652 int VorbisAvgBitrate::handle_event()
654 gui->asset->vorbis_bitrate = atol(get_text());