You're here: Snippet Directory » C/C++ (495)
Language:

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 *  

Sicherheitscode Security Code *    

RSS