00001 #include "asset.h"
00002 #include "byteorder.h"
00003 #include "clip.h"
00004 #include "file.h"
00005 #include "filevorbis.h"
00006 #include "guicast.h"
00007 #include "language.h"
00008 #include "mwindow.inc"
00009
00010 #include <errno.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014
00015 FileVorbis::FileVorbis(Asset *asset, File *file)
00016 : FileBase(asset, file)
00017 {
00018 reset_parameters();
00019 if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS;
00020 asset->byte_order = 0;
00021 }
00022
00023 FileVorbis::~FileVorbis()
00024 {
00025 close_file();
00026 }
00027
00028 void FileVorbis::get_parameters(BC_WindowBase *parent_window,
00029 Asset *asset,
00030 BC_WindowBase* &format_window,
00031 int audio_options,
00032 int video_options)
00033 {
00034 if(audio_options)
00035 {
00036 VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset);
00037 format_window = window;
00038 window->create_objects();
00039 window->run_window();
00040 delete window;
00041 }
00042 }
00043
00044 int FileVorbis::check_sig(Asset *asset)
00045 {
00046
00047 return 0;
00048 FILE *fd = fopen(asset->path, "rb");
00049 OggVorbis_File vf;
00050
00051
00052 fseek(fd, 4, SEEK_SET);
00053 char data[4];
00054 fread(data, 4, 1, fd);
00055 if(data[0] == 'm' &&
00056 data[1] == 'd' &&
00057 data[2] == 'a' &&
00058 data[3] == 't')
00059 {
00060 fclose(fd);
00061 return 0;
00062 }
00063
00064 fseek(fd, 0, SEEK_SET);
00065
00066 if(ov_open(fd, &vf, NULL, 0) < 0)
00067 {
00068
00069 ov_clear(&vf);
00070 if(fd) fclose(fd);
00071 return 0;
00072 }
00073 else
00074 {
00075 ov_clear(&vf);
00076 return 1;
00077 }
00078 }
00079
00080 int FileVorbis::reset_parameters_derived()
00081 {
00082 fd = 0;
00083 bzero(&vf, sizeof(vf));
00084 pcm_history = 0;
00085 pcm_history_float = 0;
00086 }
00087
00088
00089
00090
00091 int FileVorbis::open_file(int rd, int wr)
00092 {
00093 int result = 0;
00094 this->rd = rd;
00095 this->wr = wr;
00096
00097
00098 if(rd)
00099 {
00100
00101 if(!(fd = fopen(asset->path, "rb")))
00102 {
00103 printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
00104 result = 1;
00105 }
00106 else
00107 {
00108
00109 if(ov_open(fd, &vf, NULL, 0) < 0)
00110 {
00111 printf(_("FileVorbis::open_file %s: invalid bitstream.\n"), asset->path);
00112 result = 1;
00113 }
00114 else
00115 {
00116
00117 vorbis_info *vi = ov_info(&vf, -1);
00118 asset->channels = vi->channels;
00119 if(!asset->sample_rate)
00120 asset->sample_rate = vi->rate;
00121
00122 asset->audio_length = ov_pcm_total(&vf,-1);
00123
00124 asset->audio_data = 1;
00125
00126
00127
00128
00129 }
00130 }
00131 }
00132
00133 if(wr)
00134 {
00135 if(!(fd = fopen(asset->path, "wb")))
00136 {
00137 printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
00138 result = 1;
00139 }
00140 else
00141 {
00142 vorbis_info_init(&vi);
00143 if(!asset->vorbis_vbr)
00144 result = vorbis_encode_init(&vi,
00145 asset->channels,
00146 asset->sample_rate,
00147 asset->vorbis_max_bitrate,
00148 asset->vorbis_bitrate,
00149 asset->vorbis_min_bitrate);
00150 else
00151 {
00152 result = vorbis_encode_setup_managed(&vi,
00153 asset->channels,
00154 asset->sample_rate,
00155 asset->vorbis_max_bitrate,
00156 asset->vorbis_bitrate,
00157 asset->vorbis_min_bitrate);
00158 result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
00159 result |= vorbis_encode_setup_init(&vi);
00160 }
00161
00162 if(!result)
00163 {
00164 vorbis_analysis_init(&vd, &vi);
00165 vorbis_block_init(&vd, &vb);
00166 vorbis_comment_init(&vc);
00167 srand(time(NULL));
00168 ogg_stream_init(&os, rand());
00169
00170 ogg_packet header;
00171 ogg_packet header_comm;
00172 ogg_packet header_code;
00173 vorbis_analysis_headerout(&vd,
00174 &vc,
00175 &header,
00176 &header_comm,
00177 &header_code);
00178 ogg_stream_packetin(&os,
00179 &header);
00180 ogg_stream_packetin(&os,
00181 &header_comm);
00182 ogg_stream_packetin(&os,
00183 &header_code);
00184
00185 while(1)
00186 {
00187 int result = ogg_stream_flush(&os, &og);
00188 if(result == 0) break;
00189 fwrite(og.header, 1, og.header_len, fd);
00190 fwrite(og.body, 1, og.body_len, fd);
00191 }
00192 }
00193 }
00194 }
00195
00196
00197 return result;
00198 }
00199
00200 #define FLUSH_VORBIS \
00201 while(vorbis_analysis_blockout(&vd, &vb) == 1) \
00202 { \
00203 vorbis_analysis(&vb, NULL); \
00204 vorbis_bitrate_addblock(&vb); \
00205 while(vorbis_bitrate_flushpacket(&vd, &op)) \
00206 { \
00207 ogg_stream_packetin(&os, &op); \
00208 int done = 0; \
00209 while(1) \
00210 { \
00211 int result = ogg_stream_pageout(&os, &og); \
00212 if(!result) break; \
00213 fwrite(og.header, 1, og.header_len, fd); \
00214 fwrite(og.body, 1, og.body_len, fd); \
00215 if(ogg_page_eos(&og)) break; \
00216 } \
00217 } \
00218 }
00219
00220
00221 int FileVorbis::close_file()
00222 {
00223 if(fd)
00224 {
00225 if(wr)
00226 {
00227 vorbis_analysis_wrote(&vd, 0);
00228 FLUSH_VORBIS
00229
00230 ogg_stream_clear(&os);
00231 vorbis_block_clear(&vb);
00232 vorbis_dsp_clear(&vd);
00233 vorbis_comment_clear(&vc);
00234 vorbis_info_clear(&vi);
00235 fclose(fd);
00236 }
00237
00238 if(rd)
00239 {
00240
00241 ov_clear(&vf);
00242 }
00243 fd = 0;
00244 }
00245
00246 if(pcm_history)
00247 {
00248 for(int i = 0; i < asset->channels; i++)
00249 delete [] pcm_history[i];
00250 delete [] pcm_history;
00251 }
00252 if(pcm_history_float)
00253 {
00254 for(int i = 0; i < asset->channels; i++)
00255 delete [] pcm_history_float[i];
00256 delete [] pcm_history_float;
00257 }
00258
00259 reset_parameters();
00260 FileBase::close_file();
00261 return 0;
00262 }
00263
00264
00265 int FileVorbis::write_samples(double **buffer, int64_t len)
00266 {
00267 if(!fd) return 0;
00268 int result = 0;
00269
00270 float **vorbis_buffer = vorbis_analysis_buffer(&vd, len);
00271 for(int i = 0; i < asset->channels; i++)
00272 {
00273 float *output = vorbis_buffer[i];
00274 double *input = buffer[i];
00275 for(int j = 0; j < len; j++)
00276 {
00277 output[j] = input[j];
00278 }
00279 }
00280 vorbis_analysis_wrote(&vd, len);
00281
00282 FLUSH_VORBIS
00283
00284 return result;
00285 }
00286
00287 int FileVorbis::read_samples(double *buffer, int64_t len)
00288 {
00289 if(!fd) return 0;
00290
00291
00292
00293
00294
00295
00296 float **vorbis_output;
00297 int bitstream;
00298 int accumulation = 0;
00299
00300 int decode_start = 0;
00301 int decode_len = 0;
00302
00303 if(len > 0x100000)
00304 {
00305 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
00306 return 1;
00307 }
00308
00309 if(!pcm_history)
00310 {
00311 pcm_history = new double*[asset->channels];
00312 for(int i = 0; i < asset->channels; i++)
00313 pcm_history[i] = new double[HISTORY_MAX];
00314 history_start = 0;
00315 history_size = 0;
00316 }
00317
00318
00319 if(file->current_sample < history_start ||
00320 file->current_sample > history_start + history_size)
00321 {
00322 history_size = 0;
00323 history_start = file->current_sample;
00324 decode_start = file->current_sample;
00325 decode_len = len;
00326 }
00327 else
00328
00329 if(file->current_sample + len > history_start + history_size)
00330 {
00331 if(file->current_sample + len > history_start + HISTORY_MAX)
00332 {
00333 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
00334 for(int i = 0; i < asset->channels; i++)
00335 {
00336 double *temp = pcm_history[i];
00337 for(int j = 0; j < HISTORY_MAX - diff; j++)
00338 {
00339 temp[j] = temp[j + diff];
00340 }
00341 }
00342 history_start += diff;
00343 history_size -= diff;
00344 }
00345
00346
00347 decode_start = history_start + history_size;
00348 decode_len = file->current_sample + len - (history_start + history_size);
00349 }
00350
00351
00352
00353 if(history_start + history_size != ov_pcm_tell(&vf))
00354 {
00355
00356 ov_pcm_seek(&vf, history_start + history_size);
00357 }
00358
00359 while(accumulation < decode_len)
00360 {
00361 int result = ov_read_float(&vf,
00362 &vorbis_output,
00363 decode_len - accumulation,
00364 &bitstream);
00365
00366 if(!result) break;
00367
00368 for(int i = 0; i < asset->channels; i++)
00369 {
00370 double *output = pcm_history[i] + history_size;
00371 float *input = vorbis_output[i];
00372 for(int j = 0; j < result; j++)
00373 output[j] = input[j];
00374 }
00375 history_size += result;
00376 accumulation += result;
00377 }
00378
00379
00380
00381
00382
00383
00384 double *input = pcm_history[file->current_channel] +
00385 file->current_sample -
00386 history_start;
00387 for(int i = 0; i < len; i++)
00388 buffer[i] = input[i];
00389
00390
00391
00392
00393
00394
00395
00396 return 0;
00397 }
00398
00399 int FileVorbis::prefer_samples_float()
00400 {
00401 return 1;
00402 }
00403
00404 int FileVorbis::read_samples_float(float *buffer, int64_t len)
00405 {
00406 if(!fd) return 0;
00407
00408
00409
00410
00411
00412
00413 float **vorbis_output;
00414 int bitstream;
00415 int accumulation = 0;
00416
00417 int decode_start = 0;
00418 int decode_len = 0;
00419
00420 if(len > 0x100000)
00421 {
00422 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
00423 return 1;
00424 }
00425
00426 if(!pcm_history_float)
00427 {
00428 pcm_history_float = new float*[asset->channels];
00429 for(int i = 0; i < asset->channels; i++)
00430 pcm_history_float[i] = new float[HISTORY_MAX];
00431 history_start = 0;
00432 history_size = 0;
00433 }
00434
00435
00436 if(file->current_sample < history_start ||
00437 file->current_sample > history_start + history_size)
00438 {
00439 history_size = 0;
00440 history_start = file->current_sample;
00441 decode_start = file->current_sample;
00442 decode_len = len;
00443 }
00444 else
00445
00446 if(file->current_sample + len > history_start + history_size)
00447 {
00448 if(file->current_sample + len > history_start + HISTORY_MAX)
00449 {
00450 int diff = file->current_sample + len - (history_start + HISTORY_MAX);
00451 for(int i = 0; i < asset->channels; i++)
00452 {
00453 float *temp = pcm_history_float[i];
00454
00455
00456
00457
00458 bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float));
00459 }
00460 history_start += diff;
00461 history_size -= diff;
00462 }
00463
00464
00465 decode_start = history_start + history_size;
00466 decode_len = file->current_sample + len - (history_start + history_size);
00467 }
00468
00469
00470
00471 if(history_start + history_size != ov_pcm_tell(&vf))
00472 {
00473
00474 ov_pcm_seek(&vf, history_start + history_size);
00475 }
00476
00477 while(accumulation < decode_len)
00478 {
00479 int result = ov_read_float(&vf,
00480 &vorbis_output,
00481 decode_len - accumulation,
00482 &bitstream);
00483
00484 if(!result) break;
00485
00486 for(int i = 0; i < asset->channels; i++)
00487 {
00488 float *output = pcm_history_float[i] + history_size;
00489 float *input = vorbis_output[i];
00490
00491
00492 bcopy(input, output, result * sizeof(float));
00493 }
00494 history_size += result;
00495 accumulation += result;
00496 }
00497
00498
00499
00500
00501
00502
00503 float *input = pcm_history_float[file->current_channel] +
00504 file->current_sample -
00505 history_start;
00506
00507
00508 bcopy(input, buffer, len * sizeof(float));
00509
00510
00511
00512
00513
00514
00515
00516 return 0;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window,
00529 Asset *asset)
00530 : BC_Window(PROGRAM_NAME ": Audio Compression",
00531 parent_window->get_abs_cursor_x(1),
00532 parent_window->get_abs_cursor_y(1),
00533 350,
00534 170,
00535 -1,
00536 -1,
00537 0,
00538 0,
00539 1)
00540 {
00541 this->parent_window = parent_window;
00542 this->asset = asset;
00543 }
00544
00545 VorbisConfigAudio::~VorbisConfigAudio()
00546 {
00547 }
00548
00549 int VorbisConfigAudio::create_objects()
00550 {
00551 int x = 10, y = 10;
00552 int x1 = 150;
00553 char string[BCTEXTLEN];
00554
00555 add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this));
00556 add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this));
00557
00558 y += 30;
00559 sprintf(string, "%d", asset->vorbis_min_bitrate);
00560 add_tool(new BC_Title(x, y, _("Min bitrate:")));
00561 add_tool(new VorbisMinBitrate(x1, y, this, string));
00562
00563 y += 30;
00564 add_tool(new BC_Title(x, y, _("Avg bitrate:")));
00565 sprintf(string, "%d", asset->vorbis_bitrate);
00566 add_tool(new VorbisAvgBitrate(x1, y, this, string));
00567
00568 y += 30;
00569 add_tool(new BC_Title(x, y, _("Max bitrate:")));
00570 sprintf(string, "%d", asset->vorbis_max_bitrate);
00571 add_tool(new VorbisMaxBitrate(x1, y, this, string));
00572
00573
00574 add_subwindow(new BC_OKButton(this));
00575 show_window();
00576 flush();
00577 return 0;
00578 }
00579
00580 int VorbisConfigAudio::close_event()
00581 {
00582 set_done(0);
00583 return 1;
00584 }
00585
00586
00587
00588
00589
00590 VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui)
00591 : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate"))
00592 {
00593 this->gui = gui;
00594 }
00595 int VorbisFixedBitrate::handle_event()
00596 {
00597 gui->asset->vorbis_vbr = 0;
00598 gui->variable_bitrate->update(0);
00599 return 1;
00600 }
00601
00602 VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui)
00603 : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
00604 {
00605 this->gui = gui;
00606 }
00607 int VorbisVariableBitrate::handle_event()
00608 {
00609 gui->asset->vorbis_vbr = 1;
00610 gui->fixed_bitrate->update(0);
00611 return 1;
00612 }
00613
00614
00615 VorbisMinBitrate::VorbisMinBitrate(int x,
00616 int y,
00617 VorbisConfigAudio *gui,
00618 char *text)
00619 : BC_TextBox(x, y, 180, 1, text)
00620 {
00621 this->gui = gui;
00622 }
00623 int VorbisMinBitrate::handle_event()
00624 {
00625 gui->asset->vorbis_min_bitrate = atol(get_text());
00626 return 1;
00627 }
00628
00629
00630
00631 VorbisMaxBitrate::VorbisMaxBitrate(int x,
00632 int y,
00633 VorbisConfigAudio *gui,
00634 char *text)
00635 : BC_TextBox(x, y, 180, 1, text)
00636 {
00637 this->gui = gui;
00638 }
00639 int VorbisMaxBitrate::handle_event()
00640 {
00641 gui->asset->vorbis_max_bitrate = atol(get_text());
00642 return 1;
00643 }
00644
00645
00646
00647 VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text)
00648 : BC_TextBox(x, y, 180, 1, text)
00649 {
00650 this->gui = gui;
00651 }
00652 int VorbisAvgBitrate::handle_event()
00653 {
00654 gui->asset->vorbis_bitrate = atol(get_text());
00655 return 1;
00656 }
00657
00658
00659
00660