5 #include "filevorbis.h"
16 FileVorbis::FileVorbis(Asset_GC asset, File *file)
17 : FileBase(asset, file)
20 if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS;
21 asset->byte_order = 0;
24 FileVorbis::~FileVorbis()
29 void FileVorbis::get_parameters(BC_WindowBase *parent_window,
31 BC_WindowBase* &format_window,
37 VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset);
38 format_window = window;
39 window->create_objects();
45 int FileVorbis::check_sig(Asset_GC asset)
47 // FILEVORBIS DECODING IS DISABLED
49 FILE *fd = fopen(asset->path, "rb");
52 // Test for Quicktime since OGG misinterprets it
53 fseek(fd, 4, SEEK_SET);
55 fread(data, 4, 1, fd);
65 fseek(fd, 0, SEEK_SET);
67 if(ov_open(fd, &vf, NULL, 0) < 0)
69 // OGG failed. Close file handle manually.
81 int FileVorbis::reset_parameters_derived()
84 bzero(&vf, sizeof(vf));
86 pcm_history_float = 0;
90 // Just create the Quicktime objects since this routine is also called
92 int FileVorbis::open_file(int rd, int wr)
98 //printf("FileVorbis::open_file 1\n");
101 //printf("FileVorbis::open_file 1\n");
102 if(!(fd = fopen(asset->path, "rb")))
104 eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
109 //printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
110 if(ov_open(fd, &vf, NULL, 0) < 0)
112 eprintf("Invalid bitstream in %s\n", asset->path);
117 //printf("FileVorbis::open_file 1\n");
118 vorbis_info *vi = ov_info(&vf, -1);
119 asset->channels = vi->channels;
120 if(!asset->sample_rate)
121 asset->sample_rate = vi->rate;
122 //printf("FileVorbis::open_file 1\n");
123 asset->audio_length = ov_pcm_total(&vf,-1);
124 //printf("FileVorbis::open_file 1\n");
125 asset->audio_data = 1;
126 // printf("FileVorbis::open_file 1 %d %d %d\n",
128 // asset->sample_rate,
129 // asset->audio_length);
136 if(!(fd = fopen(asset->path, "wb")))
138 eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
143 vorbis_info_init(&vi);
144 if(!asset->vorbis_vbr)
145 result = vorbis_encode_init(&vi,
148 asset->vorbis_max_bitrate,
149 asset->vorbis_bitrate,
150 asset->vorbis_min_bitrate);
153 result = vorbis_encode_setup_managed(&vi,
156 asset->vorbis_max_bitrate,
157 asset->vorbis_bitrate,
158 asset->vorbis_min_bitrate);
159 result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
160 result |= vorbis_encode_setup_init(&vi);
165 vorbis_analysis_init(&vd, &vi);
166 vorbis_block_init(&vd, &vb);
167 vorbis_comment_init(&vc);
169 ogg_stream_init(&os, rand());
172 ogg_packet header_comm;
173 ogg_packet header_code;
174 vorbis_analysis_headerout(&vd,
179 ogg_stream_packetin(&os,
181 ogg_stream_packetin(&os,
183 ogg_stream_packetin(&os,
188 int result = ogg_stream_flush(&os, &og);
189 if(result == 0) break;
190 fwrite(og.header, 1, og.header_len, fd);
191 fwrite(og.body, 1, og.body_len, fd);
197 //printf("FileVorbis::open_file 2\n");
201 #define FLUSH_VORBIS \
202 while(vorbis_analysis_blockout(&vd, &vb) == 1) \
204 vorbis_analysis(&vb, NULL); \
205 vorbis_bitrate_addblock(&vb); \
206 while(vorbis_bitrate_flushpacket(&vd, &op)) \
208 ogg_stream_packetin(&os, &op); \
212 int result = ogg_stream_pageout(&os, &og); \
214 fwrite(og.header, 1, og.header_len, fd); \
215 fwrite(og.body, 1, og.body_len, fd); \
216 if(ogg_page_eos(&og)) break; \
222 int FileVorbis::close_file()
228 vorbis_analysis_wrote(&vd, 0);
231 ogg_stream_clear(&os);
232 vorbis_block_clear(&vb);
233 vorbis_dsp_clear(&vd);
234 vorbis_comment_clear(&vc);
235 vorbis_info_clear(&vi);
241 // This also closes the file handle.
249 for(int i = 0; i < asset->channels; i++)
250 delete [] pcm_history[i];
251 delete [] pcm_history;
253 if(pcm_history_float)
255 for(int i = 0; i < asset->channels; i++)
256 delete [] pcm_history_float[i];
257 delete [] pcm_history_float;
261 FileBase::close_file();
266 int FileVorbis::write_samples(double **buffer, int64_t len)
271 float **vorbis_buffer = vorbis_analysis_buffer(&vd, len);
272 for(int i = 0; i < asset->channels; i++)
274 float *output = vorbis_buffer[i];
275 double *input = buffer[i];
276 for(int j = 0; j < len; j++)
278 output[j] = input[j];
281 vorbis_analysis_wrote(&vd, len);
288 int FileVorbis::read_samples(double *buffer, int64_t len)
292 // printf("FileVorbis::read_samples 1 %d %d %d %d\n",
295 // file->current_sample,
297 float **vorbis_output;
299 int accumulation = 0;
300 //printf("FileVorbis::read_samples 1\n");
301 int decode_start = 0;
306 eprintf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
312 pcm_history = new double*[asset->channels];
313 for(int i = 0; i < asset->channels; i++)
314 pcm_history[i] = new double[HISTORY_MAX];
319 // Restart history. Don't bother shifting history back.
320 if(file->current_sample < history_start ||
321 file->current_sample > history_start + history_size)
324 history_start = file->current_sample;
325 decode_start = file->current_sample;
329 // Shift history forward to make room for new samples
330 if(file->current_sample + len > history_start + history_size)
332 if(file->current_sample + len > history_start + HISTORY_MAX)
334 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
335 for(int i = 0; i < asset->channels; i++)
337 double *temp = pcm_history[i];
338 for(int j = 0; j < HISTORY_MAX - diff; j++)
340 temp[j] = temp[j + diff];
343 history_start += diff;
344 history_size -= diff;
348 decode_start = history_start + history_size;
349 decode_len = file->current_sample + len - (history_start + history_size);
353 // Fill history buffer
354 if(history_start + history_size != ov_pcm_tell(&vf))
356 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
357 ov_pcm_seek(&vf, history_start + history_size);
360 while(accumulation < decode_len)
362 int result = ov_read_float(&vf,
364 decode_len - accumulation,
366 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
369 for(int i = 0; i < asset->channels; i++)
371 double *output = pcm_history[i] + history_size;
372 float *input = vorbis_output[i];
373 for(int j = 0; j < result; j++)
374 output[j] = input[j];
376 history_size += result;
377 accumulation += result;
381 // printf("FileVorbis::read_samples 1 %d %d\n",
382 // file->current_sample,
385 double *input = pcm_history[file->current_channel] +
386 file->current_sample -
388 for(int i = 0; i < len; i++)
389 buffer[i] = input[i];
391 // printf("FileVorbis::read_samples 2 %d %d %d %d\n",
394 // file->current_sample,
400 int FileVorbis::prefer_samples_float()
405 int FileVorbis::read_samples_float(float *buffer, int64_t len)
409 // printf("FileVorbis::read_samples 1 %d %d %d %d\n",
412 // file->current_sample,
414 float **vorbis_output;
416 int accumulation = 0;
417 //printf("FileVorbis::read_samples 1\n");
418 int decode_start = 0;
423 eprintf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
427 if(!pcm_history_float)
429 pcm_history_float = new float*[asset->channels];
430 for(int i = 0; i < asset->channels; i++)
431 pcm_history_float[i] = new float[HISTORY_MAX];
436 // Restart history. Don't bother shifting history back.
437 if(file->current_sample < history_start ||
438 file->current_sample > history_start + history_size)
441 history_start = file->current_sample;
442 decode_start = file->current_sample;
446 // Shift history forward to make room for new samples
447 if(file->current_sample + len > history_start + history_size)
449 if(file->current_sample + len > history_start + HISTORY_MAX)
451 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
452 for(int i = 0; i < asset->channels; i++)
454 float *temp = pcm_history_float[i];
455 // for(int j = 0; j < HISTORY_MAX - diff; j++)
457 // temp[j] = temp[j + diff];
459 bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float));
461 history_start += diff;
462 history_size -= diff;
466 decode_start = history_start + history_size;
467 decode_len = file->current_sample + len - (history_start + history_size);
471 // Fill history buffer
472 if(history_start + history_size != ov_pcm_tell(&vf))
474 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
475 ov_pcm_seek(&vf, history_start + history_size);
478 while(accumulation < decode_len)
480 int result = ov_read_float(&vf,
482 decode_len - accumulation,
484 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
487 for(int i = 0; i < asset->channels; i++)
489 float *output = pcm_history_float[i] + history_size;
490 float *input = vorbis_output[i];
491 // for(int j = 0; j < result; j++)
492 // output[j] = input[j];
493 bcopy(input, output, result * sizeof(float));
495 history_size += result;
496 accumulation += result;
500 // printf("FileVorbis::read_samples 1 %d %d\n",
501 // file->current_sample,
504 float *input = pcm_history_float[file->current_channel] +
505 file->current_sample -
507 // for(int i = 0; i < len; i++)
508 // buffer[i] = input[i];
509 bcopy(input, buffer, len * sizeof(float));
511 // printf("FileVorbis::read_samples 2 %d %d %d %d\n",
514 // file->current_sample,
529 VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window,
531 : BC_Window(PROGRAM_NAME ": Audio Compression",
532 parent_window->get_abs_cursor_x(1),
533 parent_window->get_abs_cursor_y(1),
542 this->parent_window = parent_window;
546 VorbisConfigAudio::~VorbisConfigAudio()
550 int VorbisConfigAudio::create_objects()
554 char string[BCTEXTLEN];
556 add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this));
557 add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this));
560 sprintf(string, "%d", asset->vorbis_min_bitrate);
561 add_tool(new BC_Title(x, y, _("Min bitrate:")));
562 add_tool(new VorbisMinBitrate(x1, y, this, string));
565 add_tool(new BC_Title(x, y, _("Avg bitrate:")));
566 sprintf(string, "%d", asset->vorbis_bitrate);
567 add_tool(new VorbisAvgBitrate(x1, y, this, string));
570 add_tool(new BC_Title(x, y, _("Max bitrate:")));
571 sprintf(string, "%d", asset->vorbis_max_bitrate);
572 add_tool(new VorbisMaxBitrate(x1, y, this, string));
575 add_subwindow(new BC_OKButton(this));
581 int VorbisConfigAudio::close_event()
591 VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui)
592 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate"))
596 int VorbisFixedBitrate::handle_event()
598 gui->asset->vorbis_vbr = 0;
599 gui->variable_bitrate->update(0);
603 VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui)
604 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
608 int VorbisVariableBitrate::handle_event()
610 gui->asset->vorbis_vbr = 1;
611 gui->fixed_bitrate->update(0);
616 VorbisMinBitrate::VorbisMinBitrate(int x,
618 VorbisConfigAudio *gui,
620 : BC_TextBox(x, y, 180, 1, text)
624 int VorbisMinBitrate::handle_event()
626 gui->asset->vorbis_min_bitrate = atol(get_text());
632 VorbisMaxBitrate::VorbisMaxBitrate(int x,
634 VorbisConfigAudio *gui,
636 : BC_TextBox(x, y, 180, 1, text)
640 int VorbisMaxBitrate::handle_event()
642 gui->asset->vorbis_max_bitrate = atol(get_text());
648 VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text)
649 : BC_TextBox(x, y, 180, 1, text)
653 int VorbisAvgBitrate::handle_event()
655 gui->asset->vorbis_bitrate = atol(get_text());
665 // c-file-style: "linux"