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