00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <string.h>
00041 #include <math.h>
00042
00043 #include "ogg.h"
00044 #include "ogg_silence.h"
00045 #include "ogg_utils.h"
00046 #include "silence_processors.h"
00047 #include "ogg_new_stream_handler.h"
00048
00049 static void splt_ogg_scan_silence_and_process(splt_state *state, short seconds,
00050 float max_threshold, ogg_page *page, ogg_int64_t granpos, ogg_int64_t first_cut_granpos,
00051 short process_silence(double time, int silence_was_found, short must_flush,
00052 splt_scan_silence_data *ssd, int *found, int *error),
00053 splt_scan_silence_data *ssd, int *error);
00054 static int splt_ogg_silence(splt_ogg_state *oggstate, vorbis_dsp_state *vd, float threshold);
00055
00056 int splt_ogg_scan_silence(splt_state *state, short seconds, float threshold,
00057 float min, short output, ogg_page *page, ogg_int64_t granpos,
00058 int *error, ogg_int64_t first_cut_granpos,
00059 short silence_processor(double time, int silence_was_found, short must_flush,
00060 splt_scan_silence_data *ssd, int *found, int *error))
00061 {
00062 splt_scan_silence_data *ssd = splt_scan_silence_data_new(state, output, min, SPLT_FALSE);
00063 if (ssd == NULL)
00064 {
00065 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00066 return -1;
00067 }
00068
00069 splt_ogg_scan_silence_and_process(state, seconds, threshold, page, granpos, first_cut_granpos,
00070 silence_processor, ssd, error);
00071
00072 int found = ssd->found;
00073
00074 splt_free_scan_silence_data(&ssd);
00075
00076 if (*error < 0)
00077 {
00078 found = -1;
00079 }
00080
00081 return found;
00082 }
00083
00084 static void splt_ogg_scan_silence_and_process(splt_state *state, short seconds,
00085 float max_threshold, ogg_page *page, ogg_int64_t granpos, ogg_int64_t first_cut_granpos,
00086 short process_silence(double time, int silence_was_found, short must_flush,
00087 splt_scan_silence_data *ssd, int *found, int *error),
00088 splt_scan_silence_data *ssd, int *error)
00089 {
00090 splt_c_put_progress_text(state, SPLT_PROGRESS_SCAN_SILENCE);
00091
00092 splt_ogg_state *oggstate = state->codec;
00093
00094 ogg_stream_state os;
00095 ogg_stream_init(&os, oggstate->serial);
00096
00097 splt_ogg_new_stream_handler *ogg_new_stream_handler =
00098 splt_ogg_nsh_new(state, oggstate, NULL, NULL, SPLT_FALSE, &os);
00099 if (ogg_new_stream_handler == NULL)
00100 {
00101 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00102 return;
00103 }
00104
00105 ogg_int64_t pos = granpos;
00106
00107 off_t initial_file_offset = ftello(oggstate->in);
00108 int saveW = oggstate->prevW;
00109
00110 ogg_page og;
00111
00112 float threshold = splt_co_convert_from_dB(max_threshold);
00113
00114 int result = 0;
00115
00116 vorbis_dsp_state vd;
00117 vorbis_synthesis_init(&vd, oggstate->vi);
00118
00119 vorbis_block vb;
00120 vorbis_block_init(&vd, &vb);
00121
00122 ogg_sync_state oy;
00123 ogg_sync_init(&oy);
00124
00125 int split_type = splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE);
00126 short option_silence_mode =
00127 (split_type == SPLT_OPTION_SILENCE_MODE || split_type == SPLT_OPTION_TRIM_SILENCE_MODE);
00128
00129 int found = 0;
00130
00131
00132 if (page)
00133 {
00134 memcpy(&og, page, sizeof(ogg_page));
00135 result = 1;
00136 }
00137
00138 if (option_silence_mode)
00139 {
00140 memcpy(&oy, oggstate->sync_in, sizeof(*oggstate->sync_in));
00141
00142 size_t storage_to_copy = oggstate->sync_in->storage * sizeof(unsigned char);
00143
00144 oy.data = malloc(storage_to_copy);
00145 if (oy.data == NULL)
00146 {
00147 *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
00148 goto function_end;
00149 }
00150
00151 memcpy(oy.data, oggstate->sync_in->data, storage_to_copy);
00152 }
00153
00154 ogg_int64_t end = 0, begin = 0;
00155
00156 if (seconds > 0)
00157 {
00158 end = (ogg_int64_t) (seconds * oggstate->vi->rate);
00159 }
00160
00161 oggstate->temp_level = 0.0;
00162
00163 short is_stream = SPLT_FALSE;
00164 long stream_time0 = 0;
00165
00166 int eos = 0;
00167 ogg_int64_t page_granpos;
00168 ogg_packet op;
00169
00170 double previous_streams_time_in_double = 0;
00171 double time_in_double = 0;
00172
00173 while (!eos)
00174 {
00175 while (!eos)
00176 {
00177 if (result == 0)
00178 {
00179 break;
00180 }
00181
00182 if (result > 0)
00183 {
00184 if (ogg_page_bos(&og))
00185 {
00186 splt_ogg_initialise_for_new_stream(ogg_new_stream_handler, &og, NULL, 0);
00187 oggstate->cutpoint_begin = 0;
00188 previous_streams_time_in_double = time_in_double;
00189 }
00190
00191 page_granpos = ogg_page_granulepos(&og) - oggstate->cutpoint_begin;
00192
00193 if (pos == 0)
00194 {
00195 pos = page_granpos;
00196 }
00197 ogg_stream_pagein(&os, &og);
00198
00199 while (1)
00200 {
00201 result = ogg_stream_packetout(&os, &op);
00202
00203
00204 if (result == 0)
00205 {
00206 break;
00207 }
00208
00209 if (result > 0)
00210 {
00211 if (splt_ogg_new_stream_needs_header_packet(ogg_new_stream_handler))
00212 {
00213 splt_ogg_new_stream_handle_header_packet(ogg_new_stream_handler, &op, error);
00214 if (*error < 0) { goto function_end; }
00215 continue;
00216 }
00217
00218 int bs = splt_ogg_get_blocksize(oggstate, oggstate->vi, &op);
00219
00220
00221
00222
00223 if (!splt_o_get_int_option(state, SPLT_OPT_AUTO_ADJUST))
00224 {
00225 ogg_int64_t first_granpos = splt_ogg_compute_first_granulepos(state, oggstate, &op, bs);
00226 if (first_cut_granpos == 0 && first_granpos != 0)
00227 {
00228 is_stream = SPLT_TRUE;
00229 first_cut_granpos = first_granpos;
00230 pos += first_cut_granpos;
00231 }
00232 }
00233
00234 pos += bs;
00235 if (pos > page_granpos)
00236 {
00237 pos = page_granpos;
00238 }
00239 begin += bs;
00240
00241 if (vorbis_synthesis(&vb, &op) != 0)
00242 {
00243 splt_e_set_error_data(state, splt_t_get_filename_to_split(state));
00244 *error = SPLT_ERROR_INVALID;
00245 goto function_end;
00246 }
00247
00248 vorbis_synthesis_blockin(&vd, &vb);
00249 int silence_was_found = splt_ogg_silence(oggstate, &vd, threshold);
00250
00251 int err = SPLT_OK;
00252 short must_flush = (end && begin > end);
00253 time_in_double = (double) (pos - first_cut_granpos);
00254 time_in_double /= oggstate->vi->rate;
00255 time_in_double += previous_streams_time_in_double;
00256 int stop = process_silence(time_in_double, silence_was_found, must_flush, ssd, &found, &err);
00257 if (stop || stop == -1)
00258 {
00259 eos = 1;
00260 if (err < 0) { *error = err; goto function_end; }
00261
00262 if (stop == -1)
00263 break;
00264 }
00265 }
00266 }
00267 }
00268
00269 result = ogg_sync_pageout(&oy, &og);
00270
00271
00272
00273 }
00274
00275 if (!eos)
00276 {
00277 int sync_bytes = splt_ogg_update_sync(state, &oy, oggstate->in, error);
00278 if (sync_bytes == 0)
00279 {
00280 eos = 1;
00281 }
00282 else if (sync_bytes == -1)
00283 {
00284 goto function_end;
00285 }
00286
00287 result = ogg_sync_pageout(&oy, &og);
00288
00289
00290
00291
00292
00293
00294
00295
00296 float level = splt_co_convert_to_dB(oggstate->temp_level);
00297 if (state->split.get_silence_level)
00298 {
00299 long time = (long) (((double) pos / oggstate->vi->rate) * 100.0);
00300 if (is_stream && stream_time0 == 0 && time != 0)
00301 {
00302 stream_time0 = time;
00303
00304
00305 }
00306
00307
00308
00309
00310
00311 state->split.get_silence_level(time - stream_time0, level,
00312 state->split.silence_level_client_data);
00313 }
00314 state->split.p_bar->silence_db_level = level;
00315 state->split.p_bar->silence_found_tracks = found;
00316
00317 if (option_silence_mode)
00318 {
00319 if (splt_t_split_is_canceled(state))
00320 {
00321 eos = 1;
00322 }
00323 splt_c_update_progress(state,(double)pos * 100,
00324 (double)(oggstate->len), 1,0,SPLT_DEFAULT_PROGRESS_RATE2);
00325 }
00326 else
00327 {
00328 splt_c_update_progress(state,(double)begin, (double)end, 2,0.5,SPLT_DEFAULT_PROGRESS_RATE2);
00329 }
00330 }
00331 }
00332
00333 int junk;
00334 int err = SPLT_OK;
00335 process_silence(-1, SPLT_FALSE, SPLT_FALSE, ssd, &junk, &err);
00336 if (err < 0) { *error = err; }
00337
00338 function_end:
00339
00340 ogg_stream_clear(&os);
00341
00342 vorbis_block_clear(&vb);
00343 vorbis_dsp_clear(&vd);
00344
00345 if (option_silence_mode)
00346 {
00347 if (oy.data)
00348 {
00349 free(oy.data);
00350 oy.data = NULL;
00351 }
00352 }
00353 ogg_sync_clear(&oy);
00354
00355 oggstate->prevW = saveW;
00356 if (fseeko(oggstate->in, initial_file_offset, SEEK_SET) == -1)
00357 {
00358 splt_e_set_strerror_msg_with_data(state, splt_t_get_filename_to_split(state));
00359 *error = SPLT_ERROR_SEEKING_FILE;
00360 }
00361
00362 splt_ogg_nsh_free(&ogg_new_stream_handler);
00363 }
00364
00365 static int splt_ogg_silence(splt_ogg_state *oggstate, vorbis_dsp_state *vd, float threshold)
00366 {
00367 float **pcm = NULL, sample;
00368 int samples, silence = 1;
00369
00370 while ((samples = vorbis_synthesis_pcmout(vd, &pcm)) > 0)
00371 {
00372 if (silence)
00373 {
00374 int i, j;
00375 for (i = 0; i < oggstate->vi->channels; i++)
00376 {
00377 float *mono=pcm[i];
00378 if (!silence)
00379 {
00380 break;
00381 }
00382 for(j = 0; j < samples; j++)
00383 {
00384 sample = fabs(mono[j]);
00385 oggstate->temp_level = oggstate->temp_level * 0.999 + sample * 0.001;
00386 if (sample > threshold)
00387 {
00388 silence = 0;
00389 }
00390 }
00391 }
00392 }
00393
00394 vorbis_synthesis_read(vd, samples);
00395 }
00396
00397 return silence;
00398 }
00399
00400
00401