Splitter
Language: English
Programming Language: C++
Published by: auriocus [not registered]
Last Update: 5/15/2006
Views: 378
Description
Splitter is a hack intended for splitting audio files that contain several songs into pieces so that every file contains only one song. This is especially useful for recording tapes and burning them on CD, so it is not necessary to look manually, where the different songs begin and end.It is mainly based on the input level display from krecord.
Code
1 #include <sys/types.h>
2 #include <sndfile.h>
3 #include <getopt.h>
4 #include <iostream.h>
5 #include <math.h>
6 #include <string.h>
7
8
9 void usage() {
10 cerr<<"Usage: splitter [-t threshold ] [-d delay] infile.wav [prefix] \n"
11 "Splitter tries to find the audio tracks contained "
12 "in a soundfile\n by looking for silence."
13 "It creates multiple output files containig the tracks.\n "
14 "Concatenation of these files "
15 "with an audio editor gives the original file\n "
16 "except that silence is possibly removed.\n\n"
17 "Splitter takes the following options:\n\n"
18 " -t threshold value\tthe value in dezibel that indicates \n\t\t\tsilence, -35 dB by default\n"
19 " -d minimum delay\tthe minum delay splitter waits when detecting \n\t\t\ta silence befor it really splits (1.5 seconnds by default)\n";
20
21
22 exit(1);
23 }
24
25 const int CD_SAMPLERATE=44100;
26 //const int bufsize=2048;
27 #define bufsize 2048
28 const int MAXPATH=300;
29
30 template <class T> T max (const T& a, const T& b) {
31 return (a>b)?a:b;
32 }
33
34 float compute_dB(const short* sdata, int samples, int channels) {
35 // computes a deziBel value for the input data in sdata
36 // algorithm originally from krecord
37 // used to find the silence
38 int maxLeft = 0;
39 int maxRight = 0;
40 int i;
41 int maxAmp;
42 int64_t powerLeft=0;
43 int64_t powerRight=0;
44 float floatPowerLeft=0;
45 float floatPowerRight=0;
46
47 #ifndef NO_COMPENSATE_BIAS
48 int64_t bLeft=0;
49 int64_t bRight=0;
50 #endif
51 /*
52 Calculate power of the signal depending on format.
53
54 Since the signal may not have an average value of 0 precisely,
55 we shouldn't simply calculate:
56
57 sum_for_all_samples (pulse_value) / number_of_samples
58
59 but this formula assumes that the average is zero, which is not
60 always true (for example, in 8 bits on a Sound Blaster 64,
61 there is always a shift by one unit.
62
63 We could calculate in two passes, first the average, then the
64 power of the measure minus the average. But we can do this in
65 one pass.
66
67 Let measure = signal + bias,
68 where measure is the pulse value,
69 signal is what we want,
70 bias is a constant, such that the average of signal is zero.
71
72 What we want is the value of: power = sum_for_all_samples (signal)
73
74 Let's calculate in the same pass:
75 a=sum_for_all_samples (measure)
76 and
77 b=sum_for_all_samples (measure)
78
79 Then a and b are equivalent to:
80 a = sum_for_all_samples (measure)
81 = sum_for_all_samples ((signal + bias))
82 = sum_for_all_samples (signal + bias)
83 = sum_for_all_samples (signal) + number_of_samples * bias
84
85 and
86 b = sum_for_all_samples (measure)
87 = bias * number_of_samples
88 that is, number_of_samples * bias = b / number_of_samples
89
90 So a = power + b / number_of_samples
91
92 And power = a - b / number_of_samples
93
94 So we've got the correct power of the signal in one pass.
95
96 */
97
98 #ifndef NO_COMPENSATE_BIAS
99 bLeft=0;
100 bRight=0;
101 #endif
102
103 maxAmp = 32768;
104 if (channels == 1) {
105 for (i = 0; i < samples; i++) {
106 /* Since we calculate the square of something that can be
107 as big as +-32767 we assume a width of at least 32 bits
108 for a signed int. Moreover, we add a thousand of these
109 to calculate power, so 32 bits aren't enough. I chose 64
110 bits unsigned int for precision. We could have switched
111 to float or double instead... */
112 signed int thispulse=(sdata[i]);
113 /* Note: we calculate max value anyway, to detect clipping */
114 if (abs(thispulse) > maxLeft) maxLeft = abs(sdata[i]);
115 powerLeft+=(thispulse*thispulse);
116 #ifndef NO_COMPENSATE_BIAS
117 bLeft+=thispulse;
118 #endif
119 }
120 } else
121 if (channels == 2) {
122 for (i = 0; i < samples; i++) {
123 signed int thispulse=(sdata[i*2]);
124 if (abs(thispulse) > maxLeft) maxLeft = abs(thispulse);
125 powerLeft+=(thispulse*thispulse);
126 thispulse=(sdata[i*2+1]);
127 if (abs(thispulse) > maxRight) maxRight = abs(thispulse);
128 powerRight+=(thispulse*thispulse);
129 #ifndef NO_COMPENSATE_BIAS
130 bRight+=thispulse;
131 #endif
132 }
133 }
134 /* Ok for raw power. Now normalize it. */
135
136 #ifndef NO_COMPENSATE_BIAS
137 powerLeft-=bLeft*bLeft/samples;
138 powerRight-=bRight*bRight/samples;
139 //fprintf(stderr, "bLeft: %lld\tbiais: %f\t", bLeft, ((float)bLeft*(float)maxAmp/(float)samples));
140 #endif
141
142 floatPowerLeft=((float)powerLeft)/((float)maxAmp)/((float)maxAmp)/((float)samples);
143 floatPowerRight=((float)powerLeft)/((float)maxAmp)/((float)maxAmp)/((float)samples);
144
145 //fprintf(stderr, "brute: %lld,\tnormalise: %f\t", powerLeft, floatPowerLeft);
146
147 // float dBvalue=1+0.1*log10(floatPowerLeft); /* 10/100 = 0.1 */
148 return max(10*log10(floatPowerLeft), 10*log10(floatPowerRight));
149 }
150
151 int main(int argc, char **argv) {
152 // reads a soundfile with libsndfile and splits it into pieces
153 // that contain no silence longer then maxsilence
154 // useful for splitting music from a tape deck for burning
155 // on CD-ROM
156 float silence_threshold=-35.0;
157 float maxsilence=1.5;
158 char *prefix="out";
159 char *suffix=".wav";
160 int silencecount;
161 bool outputfile_open=false;
162 int outputfile_number=1;
163 char *outputfilename=new char[MAXPATH];
164 char *inputfilename;
165
166 SF_INFO source_info,output_info;
167 SNDFILE *inputfile, *outputfile;
168
169 char c;
170 char *optchars="t:d:";
171 float temp;
172 while ((c = getopt (argc, argv, optchars)) != EOF)
173 switch (c)
174 {
175 case 'd':
176 temp=atof(optarg);
177 if (temp>0.1) maxsilence=temp;
178 else {
179 cerr<<"Error: Minimum delay must be more than 0.1 second\n";
180 usage();
181 }
182 break;
183 case 't':
184 temp=atof(optarg);
185 if (temp<-10.0) silence_threshold=temp;
186 else {
187 cerr<<"Error: Silence threshold must be below -10.0 dB\n";
188 usage();
189 }
190 break;
191 default:
192 cerr<<"Error: Unrecognized option "<<c<<"\n";
193 usage();
194
195 }
196
197 if (optind>=argc) {
198 cerr<<"Error: No input file specified\n";
199 usage(); // there is no input file after the options
200 } else {
201 inputfilename=strdup(argv[optind++]);
202 if (optind<argc) {
203 // explicit prefix given
204 prefix=strdup(argv[optind]);
205 cerr<<"Setting prefix to: "<<prefix<<"\n";
206 }
207 }
208
209 cerr<<"Opening file:"<<inputfilename<<"\n";
210 inputfile=sf_open_read(inputfilename, &source_info);
211 if (!inputfile) {
212 cerr<<"Error: Can't open file "<<inputfilename<<"\n";
213 usage();
214 }
215
216 int samplerate=source_info.samplerate;
217 int channels=source_info.channels;
218
219 if (abs(samplerate-CD_SAMPLERATE)>5) {
220 cerr<<"Error: Must be a file with CD-Samplerate "<<CD_SAMPLERATE<<" Hz, not "<<samplerate<<"\n.";
221 exit(1);
222 }
223 output_info=source_info;
224 output_info.samplerate=CD_SAMPLERATE;
225
226 int maxsilencecount=(int)(maxsilence*samplerate/bufsize);
227
228 cerr<<"Maximum silence count is "<<maxsilencecount<<"\n";;
229 cerr<<"Number of Channels: "<<channels<<"\n";
230
231 short * audiobuffer=new short[bufsize*channels];
232
233 silencecount=1;
234 // program should start with first piece, when we
235 // reach the threshold value for the first time
236 int samples_read;
237 while ((samples_read=sf_readf_short(inputfile,audiobuffer,bufsize))>0) {
238 // until the end of the file read data
239 float dBvalue=compute_dB(audiobuffer,samples_read,channels);
240 if (dBvalue<silence_threshold) {
241 silencecount++;
242 if (silencecount>=maxsilencecount) {
243 // close the output file
244 // and increment the counter
245 if (outputfile_open) {
246 sf_close(outputfile);
247 outputfile_open=false;
248 cerr<<"Closed file: "<<outputfilename<<" at threshold "<<dBvalue<<"\n";
249 outputfile_number++;
250 }
251 } else {
252 // we are in a short silence that should be ignored, i.e. written to the outputfile
253 if (outputfile_open) { sf_writef_short(outputfile,audiobuffer,bufsize);
254 }
255 }
256
257 } else {
258 // we reached the threshold value
259 // if outputfile is closed, open it
260
261 if (!outputfile_open) {
262 sprintf(outputfilename, "%s%d%s",prefix,outputfile_number,suffix);
263 outputfile=sf_open_write(outputfilename,&output_info);
264 cerr<<"Opened file: "<<outputfilename<<" at threshold "<<dBvalue<<"\n";
265 outputfile_open=true;
266 }
267
268 sf_writef_short(outputfile,audiobuffer,bufsize);
269 silencecount=0;
270 // show progress
271 }
272 }
273 sf_close(inputfile);
274 if (outputfile_open) sf_close(outputfile);
275
276 }
No comments avaiable
Add a comment
Name *
Email (won't be displayed) *
Website
Comment *
Security Code *