1 /**********************************************************
2  * libmp3splt -- library based on mp3splt,
3  *               for mp3/ogg splitting without decoding
4  *
5  * Copyright (c) 2002-2005 M. Trotta - <mtrotta@users.sourceforge.net>
6  * Copyright (c) 2005-2014 Alexandru Munteanu - m@ioalex.net
7  *
8  *********************************************************/
9 
10 /**********************************************************
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
24  * USA.
25  *********************************************************/
26 
27 #include "silence_processors.h"
28 
29 static void write_to_full_log(splt_state *state, double time, float level, int shots, int found,
30     double begin_position, double end_position);
31 
splt_scan_silence_data_new(splt_state * state,short first,float min,int shots,short set_new_length)32 splt_scan_silence_data *splt_scan_silence_data_new(splt_state *state, short first,
33     float min, int shots, short set_new_length)
34 {
35   splt_scan_silence_data *ssd = malloc(sizeof(splt_scan_silence_data));
36   if (!ssd)
37   {
38     return NULL;
39   }
40 
41   ssd->state = state;
42   ssd->first = first;
43   ssd->min = min;
44   ssd->number_of_shots = shots;
45   ssd->set_new_length = set_new_length;
46 
47   ssd->flush = SPLT_FALSE;
48   ssd->silence_begin = 0;
49   ssd->silence_end = 0;
50   ssd->len = 0;
51   ssd->found = 0;
52   ssd->shot = shots;
53   ssd->silence_begin_was_found = SPLT_FALSE;
54   ssd->continue_after_silence = SPLT_FALSE;
55   ssd->previous_time = 0;
56 
57   return ssd;
58 }
59 
splt_free_scan_silence_data(splt_scan_silence_data ** ssd)60 void splt_free_scan_silence_data(splt_scan_silence_data **ssd)
61 {
62   if (!ssd || !*ssd)
63   {
64     return;
65   }
66 
67   free(*ssd);
68   *ssd = NULL;
69 }
70 
splt_scan_silence_processor(double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found_silence_points,int * error)71 short splt_scan_silence_processor(double time, float level, int silence_was_found,
72     short must_flush, splt_scan_silence_data *ssd, int *found_silence_points, int *error)
73 {
74   if (time < 0) { return SPLT_TRUE; }
75 
76   short stop = SPLT_FALSE;
77 
78   if (must_flush)
79   {
80     ssd->flush = SPLT_TRUE;
81     stop = SPLT_TRUE;
82   }
83 
84   if (!ssd->flush && silence_was_found)
85   {
86     if (ssd->len == 0)
87     {
88       ssd->silence_begin = time;
89     }
90 
91     if (ssd->first == SPLT_FALSE)
92     {
93       ssd->len++;
94     }
95 
96     if (ssd->shot < ssd->number_of_shots)
97     {
98       ssd->shot += 2;
99     }
100 
101     ssd->silence_end = time;
102 
103     *found_silence_points = ssd->found;
104 
105     write_to_full_log(ssd->state, time, level, ssd->shot, ssd->found, -1, -1);
106     return stop;
107   }
108 
109   double begin_position = -1;
110   double end_position = -1;
111 
112   if (ssd->len > SPLT_DEFAULTSILLEN)
113   {
114     if (ssd->flush || (ssd->shot <= 0))
115     {
116       begin_position = ssd->silence_begin;
117       end_position = ssd->silence_end;
118 
119       if (ssd->set_new_length)
120       {
121         ssd->len = (int) (ssd->silence_end * 100.0 - ssd->silence_begin * 100.0);
122       }
123 
124       if ((end_position - begin_position - ssd->min) >= 0.f)
125       {
126         if (splt_siu_ssplit_new(&ssd->state->silence_list,
127               begin_position, end_position, ssd->len, error) == -1)
128         {
129           ssd->found = -1;
130           *found_silence_points = ssd->found;
131 
132           write_to_full_log(ssd->state, time, level, ssd->shot, ssd->found, begin_position, end_position);
133           return SPLT_TRUE;
134         }
135 
136         ssd->found++;
137       }
138 
139       ssd->len = 0;
140       ssd->shot = ssd->number_of_shots;
141     }
142   }
143   else
144   {
145     ssd->len = 0;
146   }
147 
148   if (ssd->flush)
149   {
150     write_to_full_log(ssd->state, time, level, ssd->shot, ssd->found, begin_position, end_position);
151     return -1;
152   }
153 
154   if (ssd->first && (ssd->shot <= 0))
155   {
156     ssd->first = SPLT_FALSE;
157   }
158 
159   if (ssd->shot > 0)
160   {
161     ssd->shot--;
162   }
163 
164   if (ssd->found >= SPLT_MAXSILENCE)
165   {
166     stop = SPLT_TRUE;
167   }
168 
169   *found_silence_points = ssd->found;
170 
171   write_to_full_log(ssd->state, time, level, ssd->shot, ssd->found, begin_position, end_position);
172   return stop;
173 }
174 
write_to_full_log(splt_state * state,double time,float level,int shots,int found,double begin_position,double end_position)175 static void write_to_full_log(splt_state *state, double time, float level, int shots, int found,
176     double begin_position, double end_position)
177 {
178   FILE *full_log_file_descriptor = splt_t_get_silence_full_log_file_descriptor(state);
179   if (!full_log_file_descriptor)
180   {
181     return;
182   }
183 
184   if (begin_position > 0 && end_position > 0)
185   {
186     fprintf(full_log_file_descriptor, "0\t%lf\t%f\t%d\t%d\t%lf\t%lf\n", time, level, shots, found,
187         begin_position, end_position);
188     return;
189   }
190 
191   fprintf(full_log_file_descriptor, "0\t%lf\t%f\t%d\t%d\t\t\n", time, level, shots, found);
192 }
193 
splt_detect_where_begin_silence_ends(double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found_silence_points,int * error)194 static short splt_detect_where_begin_silence_ends(double time, float level, int silence_was_found,
195     short must_flush, splt_scan_silence_data *ssd, int *found_silence_points, int *error)
196 {
197   if (silence_was_found)
198   {
199     if (ssd->shot < ssd->number_of_shots)
200     {
201       ssd->shot += 2;
202     }
203 
204     ssd->silence_end = time;
205   }
206 
207   if (ssd->shot <= 0)
208   {
209     double silence_end = ssd->silence_end;
210 
211     float min_length = splt_o_get_float_option(ssd->state, SPLT_OPT_PARAM_MIN_LENGTH);
212     if (min_length > 0)
213     {
214       if (silence_end > min_length)
215       {
216         silence_end -= min_length;
217       }
218       else
219       {
220         silence_end = 0;
221       }
222 
223       long mins, secs, hundr;
224       splt_co_get_mins_secs_hundr(splt_co_time_to_long(silence_end), &mins, &secs, &hundr);
225       splt_c_put_info_message_to_client(ssd->state,
226           _(" info: trim begin split at %ldm_%.2lds_%.2ldh\n"), mins, secs, hundr);
227     }
228 
229     if (splt_siu_ssplit_new(&ssd->state->silence_list, silence_end, silence_end, 0, error) == -1)
230     {
231       return SPLT_TRUE;
232     }
233 
234     ssd->found++;
235     ssd->silence_begin_was_found = SPLT_TRUE;
236     ssd->shot = ssd->number_of_shots;
237   }
238 
239   if (ssd->shot > 0)
240   {
241     ssd->shot--;
242   }
243 
244   return SPLT_FALSE;
245 }
246 
splt_detect_where_end_silence_begins(double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found_silence_points,int * error)247 static short splt_detect_where_end_silence_begins(double time, float level, int silence_was_found,
248     short must_flush, splt_scan_silence_data *ssd, int *found_silence_points, int *error)
249 {
250   if (time < 0)
251   {
252     double silence_begin = ssd->silence_begin;
253 
254     float min_length = splt_o_get_float_option(ssd->state, SPLT_OPT_PARAM_MIN_LENGTH);
255     if (min_length > 0)
256     {
257       if (ssd->previous_time - silence_begin > min_length)
258       {
259         silence_begin += min_length;
260       }
261       else
262       {
263         silence_begin = ssd->previous_time;
264       }
265 
266       long mins, secs, hundr;
267       splt_co_get_mins_secs_hundr(splt_co_time_to_long(silence_begin), &mins, &secs, &hundr);
268       splt_c_put_info_message_to_client(ssd->state,
269           _(" info: trim end split at %ldm_%.2lds_%.2ldh\n"), mins, secs, hundr);
270     }
271 
272     if (splt_siu_ssplit_new(&ssd->state->silence_list, silence_begin, silence_begin, 0, error) == -1)
273     {
274       return SPLT_TRUE;
275     }
276 
277     ssd->found++;
278 
279     return SPLT_TRUE;
280   }
281 
282   ssd->previous_time = time;
283 
284   if (silence_was_found)
285   {
286     if (ssd->len == 0)
287     {
288       ssd->silence_begin = time;
289       ssd->continue_after_silence = SPLT_FALSE;
290     }
291 
292     if (ssd->first == SPLT_FALSE)
293     {
294       ssd->len++;
295     }
296 
297     if (ssd->shot < ssd->number_of_shots)
298     {
299       ssd->shot += 2;
300     }
301 
302     return SPLT_FALSE;
303   }
304   else if (ssd->continue_after_silence)
305   {
306     ssd->silence_begin = time;
307   }
308 
309   if (ssd->len > SPLT_DEFAULTSILLEN)
310   {
311     if (ssd->shot <= 0)
312     {
313       ssd->len = 0;
314       ssd->shot = ssd->number_of_shots;
315       ssd->continue_after_silence = SPLT_TRUE;
316     }
317   }
318   else
319   {
320     ssd->len = 0;
321   }
322 
323   if (ssd->first && (ssd->shot <= 0))
324   {
325     ssd->first = SPLT_FALSE;
326   }
327 
328   if (ssd->shot > 0)
329   {
330     ssd->shot--;
331   }
332 
333   return SPLT_FALSE;
334 }
335 
splt_trim_silence_processor(double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found_silence_points,int * error)336 short splt_trim_silence_processor(double time, float level, int silence_was_found,
337     short must_flush, splt_scan_silence_data *ssd, int *found_silence_points, int *error)
338 {
339   if (!ssd->silence_begin_was_found)
340   {
341     splt_detect_where_begin_silence_ends(time, level, silence_was_found, must_flush, ssd, found_silence_points, error);
342   }
343   else
344   {
345     splt_detect_where_end_silence_begins(time, level, silence_was_found, must_flush, ssd, found_silence_points, error);
346   }
347 
348   return SPLT_FALSE;
349 }
350 
351