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