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 <stdio.h>
28 
29 #include "mp3.h"
30 #include "mp3_silence.h"
31 #include "mp3_utils.h"
32 #include "silence_processors.h"
33 
34 static void splt_mp3_scan_silence_and_process(splt_state *state, off_t begin_offset,
35     float max_threshold, unsigned long length,
36     short process_silence(double time, float level, int silence_was_found, short must_flush,
37       splt_scan_silence_data *ssd, int *found, int *error),
38     splt_scan_silence_data *ssd, int *error);
39 static int splt_mp3_silence(splt_mp3_state *mp3state, int channels, mad_fixed_t threshold);
40 
41 /*! scan for silence
42 
43 \return
44  - the number of silence points found
45  - -1 on error
46 \param state The central structure libmp3splt keeps all of its data in
47 \param error Contains the error number if an error has occoured
48 \param length The time length to scan [in seconds]
49 \param threshold The threshold that tells noise from silence
50 */
splt_mp3_scan_silence(splt_state * state,off_t begin,unsigned long length,float threshold,float min,int shots,short output,int * error,short silence_processor (double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found,int * error))51 int splt_mp3_scan_silence(splt_state *state, off_t begin, unsigned long length,
52     float threshold, float min, int shots, short output, int *error,
53     short silence_processor(double time, float level, int silence_was_found, short must_flush,
54       splt_scan_silence_data *ssd, int *found, int *error))
55 {
56   splt_scan_silence_data *ssd = splt_scan_silence_data_new(state, output, min, shots, SPLT_TRUE);
57   if (ssd == NULL)
58   {
59     *error = SPLT_ERROR_CANNOT_ALLOCATE_MEMORY;
60     return -1;
61   }
62 
63   splt_mp3_scan_silence_and_process(state, begin, threshold, length, silence_processor, ssd, error);
64 
65   int found = ssd->found;
66 
67   splt_free_scan_silence_data(&ssd);
68 
69   if (*error < 0)
70   {
71     found = -1;
72   }
73 
74   return found;
75 }
76 
splt_mp3_scan_silence_and_process(splt_state * state,off_t begin_offset,float max_threshold,unsigned long length,short process_silence (double time,float level,int silence_was_found,short must_flush,splt_scan_silence_data * ssd,int * found,int * error),splt_scan_silence_data * ssd,int * error)77 static void splt_mp3_scan_silence_and_process(splt_state *state, off_t begin_offset,
78     float max_threshold, unsigned long length,
79     short process_silence(double time, float level, int silence_was_found, short must_flush,
80       splt_scan_silence_data *ssd, int *found, int *error),
81     splt_scan_silence_data *ssd, int *error)
82 {
83   int found = 0;
84   short stop = SPLT_FALSE;
85 
86   mad_fixed_t threshold = mad_f_tofixed(splt_co_convert_from_db(max_threshold));
87 
88   splt_mp3_state *mp3state = state->codec;
89 
90   splt_c_put_progress_text(state, SPLT_PROGRESS_SCAN_SILENCE);
91 
92   //seek to the begin
93   if (fseeko(mp3state->file_input, begin_offset, SEEK_SET) == -1)
94   {
95     splt_e_set_strerror_msg_with_data(state, splt_t_get_filename_to_split(state));
96     *error = SPLT_ERROR_SEEKING_FILE;
97     return;
98   }
99 
100   //initialise mad stuff
101   splt_mp3_init_stream_frame(mp3state);
102   mad_synth_init(&mp3state->synth);
103 
104   mad_timer_reset(&mp3state->timer);
105 
106   mp3state->temp_level = 0.0;
107 
108   do {
109     int mad_err = SPLT_OK;
110 
111     int result = splt_mp3_get_valid_frame(state, &mad_err);
112 
113     switch (result)
114     {
115       case -1:
116       case 1:
117         //1 we have a valid frame
118         mad_timer_add(&mp3state->timer, mp3state->frame.header.duration);
119         mad_synth_frame(&mp3state->synth, &mp3state->frame);
120         unsigned long time = (unsigned long) mad_timer_count(mp3state->timer, MAD_UNITS_CENTISECONDS);
121 
122         int silence_was_found =
123           splt_mp3_silence(mp3state, MAD_NCHANNELS(&mp3state->frame.header), threshold);
124 
125         float level = splt_co_convert_to_db(mad_f_todouble(mp3state->temp_level));
126         if (level < -96.0) { level = -96.0; }
127         if (level > 0) { level = 0; }
128 
129         int err = SPLT_OK;
130         short must_flush = (length > 0 && time >= length);
131         double time_in_double = (double) time / 100.f;
132         stop = process_silence(time_in_double, level, silence_was_found, must_flush, ssd, &found, &err);
133         if (stop || stop == -1)
134         {
135           stop = SPLT_TRUE;
136           if (err < 0) { *error = err; goto end; }
137         }
138 
139         if (mp3state->mp3file.len > 0)
140         {
141           off_t pos = ftello(mp3state->file_input);
142 
143           if (state->split.get_silence_level)
144           {
145             state->split.get_silence_level(time, level, state->split.silence_level_client_data);
146           }
147           state->split.p_bar->silence_db_level = level;
148           state->split.p_bar->silence_found_tracks = found;
149 
150           //if we don't have silence split,
151           //put the 1/4 of progress
152           if ((splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_SILENCE_MODE) &&
153               (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) != SPLT_OPTION_TRIM_SILENCE_MODE))
154           {
155             splt_c_update_progress(state,(double)(time),
156                 (double)(length), 4,1/(float)4, SPLT_DEFAULT_PROGRESS_RATE);
157           }
158           else
159           {
160             if (splt_t_split_is_canceled(state))
161             {
162               //split cancelled
163               stop = SPLT_TRUE;
164             }
165             splt_c_update_progress(state,(double)pos,
166                 (double)(mp3state->mp3file.len), 1,0,SPLT_DEFAULT_PROGRESS_RATE);
167           }
168         }
169 
170         //-1 means eof
171         if (result == -1)
172         {
173           stop = SPLT_TRUE;
174         }
175         break;
176       case 0:
177         //0 do nothing
178         break;
179       case -3:
180         //error from libmad
181         stop = SPLT_TRUE;
182         *error = mad_err;
183         break;
184       default:
185         break;
186     }
187 
188   } while (!stop);
189 
190   int junk;
191   int err = SPLT_OK;
192   process_silence(-1, -96, SPLT_FALSE, SPLT_FALSE, ssd, &junk, &err);
193   if (err < 0) { *error = err; }
194 
195   //only if we have silence mode, we set progress to 100%
196   if ((splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) == SPLT_OPTION_SILENCE_MODE) ||
197       (splt_o_get_int_option(state, SPLT_OPT_SPLIT_MODE) == SPLT_OPTION_TRIM_SILENCE_MODE))
198   {
199     splt_c_update_progress(state,1.0,1.0,1,1,1);
200   }
201 
202 end:
203   //finish with mad_*
204   splt_mp3_finish_stream_frame(mp3state);
205   mad_synth_finish(&mp3state->synth);
206 }
207 
208 /*!  Compare the noise level with threshold
209 
210 Used by mp3_scan_silence
211 
212 \return
213  - 0 if silence spot > threshold,
214  - 1 otherwise
215 
216 Always computes only one frame
217 */
splt_mp3_silence(splt_mp3_state * mp3state,int channels,mad_fixed_t threshold)218 static int splt_mp3_silence(splt_mp3_state *mp3state, int channels, mad_fixed_t threshold)
219 {
220   int i, j;
221   mad_fixed_t sample;
222   int silence = 1;
223 
224   for (j = 0; j < channels; j++)
225   {
226     for(i = 0; i < mp3state->synth.pcm.length; i++)
227     {
228       sample = mad_f_abs(mp3state->synth.pcm.samples[j][i]);
229       mp3state->temp_level = mp3state->temp_level * 0.999 + sample * 0.001;
230 
231       if (sample > threshold)
232       {
233         silence = 0;
234       }
235     }
236   }
237 
238   return silence;
239 }
240 
241