00001
00006 #include <iostream>
00007
00008 #include "mp3core.h"
00009 #include "mp3frame.h"
00010 #include "mp3iterator.h"
00011 #include "bitstream.h"
00012 #include "except.h"
00013 #include "conv.h"
00014
00015 MP3Core::MP3Core()
00016 {
00017 m_outfile = 0;
00018 m_infiles = 0;
00019 m_showinfo = false;
00020 m_gain = 0;
00021 m_cutstart = m_cutend = 0;
00022 m_autocutstart = false;
00023 m_autocutend = false;
00024 m_numframes = 0;
00025 }
00026
00027 bool MP3Core::Params(int argc, const char *argv[])
00028 {
00029 int i;
00030
00031
00032 for(i = 1; i < argc - 1; i++)
00033 {
00034 if(argv[i][0] == '-' && argv[i][1])
00035 {
00036 switch(argv[i][1])
00037 {
00038 case 'h':
00039 return false;
00040 case 'o':
00041 m_outfile = argv[++i];
00042 break;
00043 case 'g':
00044 m_gain = Conv::dB2Gain(argv[++i]);
00045 break;
00046 case 'v':
00047 m_showinfo = true;
00048 break;
00049 case 'c':
00050 switch(argv[i][2])
00051 {
00052 case 's':
00053 if(*argv[++i] == 'a')
00054 m_autocutstart = true;
00055 else
00056 m_cutstart = Conv::Time2Frame(argv[i]);
00057 break;
00058 case 'e':
00059 if(*argv[++i] == 'a')
00060 m_autocutend = true;
00061 else
00062 m_cutend = Conv::Time2Frame(argv[i]);;
00063 break;
00064 }
00065 break;
00066 case 't':
00067 i += m_tag.ParseParam(argv[i][2], argv[i+1]);
00068 break;
00069 }
00070 }
00071 else
00072 break;
00073 }
00074
00075 m_infiles = argv + i;
00076 return argc > i;
00077 }
00078
00079 void MP3Core::GetInfo()
00080 {
00081 bool start = m_autocutstart;
00082 int numloud = 0;
00083 int avgbitrate = 0;
00084
00085 try {
00086 Bitstream bs(m_infiles, Bitstream::in);
00087 MP3Iterator frame(bs, MP3Frame::nowrite);
00088
00089 if(m_showinfo)
00090 {
00091 m_tag.Show(std::cout);
00092 frame->ShowInfo(std::cout);
00093 }
00094
00095 while(true)
00096 {
00097
00098 if( !m_outfile && frame->CorruptionFound() )
00099 std::cerr << "Corruption found at " << Conv::Frame2Time(m_numframes) << "!" << std::endl;
00100
00101 avgbitrate += frame->Bitrate();
00102 m_numframes++;
00103
00104 if(m_autocutstart && start)
00105 {
00106 if( frame->isSilent() )
00107 {
00108 m_cutstart = m_numframes;
00109 numloud = 0;
00110 }
00111 else if(++numloud > mp3::maxloud)
00112 start = false;
00113 }
00114
00115 if(m_autocutend && !start)
00116 {
00117 if( frame->isSilent() )
00118 numloud = 0;
00119 else if(++numloud > mp3::maxloud)
00120 m_cutend = m_numframes;
00121 }
00122
00123 ++frame;
00124 }
00125 }
00126 catch(eEOF)
00127 {
00128 avgbitrate /= m_numframes;
00129
00130 if(m_autocutend)
00131 m_cutend = m_numframes - m_cutend;
00132
00133 if(m_showinfo)
00134 {
00135 std::cout << "Duration: " << Conv::Frame2Time(m_numframes) << std::endl;
00136 std::cout << "Average bitrate: " << avgbitrate << " kbps" << std::endl;
00137
00138 if(m_autocutstart || m_autocutend)
00139 std::cout << "Silence: " << Conv::Frame2Time(m_cutstart) << " at the beginning and "
00140 << Conv::Frame2Time(m_cutend) << " at the end." << std::endl;
00141 }
00142 }
00143 }
00144
00145 bool MP3Core::WriteResult()
00146 {
00147 int j = 0;
00148
00149 try {
00150 Bitstream bs(m_infiles, Bitstream::in);
00151 Bitstream bs_out(m_outfile, Bitstream::out);
00152
00153
00154
00155 MP3Iterator frame(bs, (m_cutstart == 0) ? MP3Frame::fastwrite : MP3Frame::normal);
00156
00157 while(true)
00158 {
00159 if( frame->CorruptionFound() )
00160 std::cerr << "Corruption found at " << Conv::Frame2Time(j) << "!" << std::endl;
00161
00162 if(m_gain) frame->ChangeGain(m_gain);
00163
00164 if(m_cutend && j >= m_numframes - m_cutend)
00165 break;
00166
00167
00168
00169 if(j == m_cutstart)
00170 frame->SetFirst();
00171
00172 if(j >= m_cutstart)
00173 try {
00174 frame->Write(bs_out);
00175 }
00176 catch(eCannotProceed e)
00177 {
00178 std::cerr << "Sorry, this operation is not possible: " << e.what() << std::endl;
00179 return false;
00180 }
00181
00182 ++frame;
00183 j++;
00184 }
00185 }
00186 catch(eEOF) { }
00187
00188 m_tag.Write(m_outfile);
00189 return true;
00190 }
00191
00192 bool MP3Core::Process()
00193 {
00194 try {
00195 m_tag.Read(*m_infiles);
00196
00197
00198 if(m_showinfo || m_cutend || m_autocutstart || m_autocutend || !m_outfile)
00199 GetInfo();
00200
00201 if(m_outfile)
00202 return WriteResult();
00203 }
00204 catch(eOpenFailed e)
00205 {
00206 std::cerr << "Can't open file `" << e.filename() << "'!" << std::endl;
00207 return false;
00208 }
00209
00210 return true;
00211 }
00212
00213 void MP3Core::ShowHelp(const char *filename)
00214 {
00215 std::cout << "Tool for various lossless operations on MP3 files." << std::endl;
00216 std::cout << "Usage: " << filename << " [parameters] input files" << std::endl;
00217 std::cout << "Parameters: " << std::endl;
00218 std::cout << " -o file.mp3 Output file (input files are never changed!) " << std::endl;
00219 std::cout << " -g N Change volume by N dB " << std::endl;
00220 std::cout << " -v Show file duration, bitrate, tag information etc. " << std::endl;
00221 std::cout << " -cs time Cut specified time from beginning of file, " << std::endl;
00222 std::cout << " if time is 'a', digital silence is removed " << std::endl;
00223 std::cout << " -cs time Cut specified time from end of file, " << std::endl;
00224 std::cout << " if time is 'a', digital silence is removed " << std::endl;
00225 std::cout << " -t1 Keep ID3v1 tag (or create when some field is set) " << std::endl;
00226 std::cout << " -t2 Keep ID3v1 tag (or create when some field is set) " << std::endl;
00227 std::cout << " -tx Don't read ID3 tags, create from scratch " << std::endl;
00228 std::cout << " -tt value Set Title field in ID3 tag " << std::endl;
00229 std::cout << " -ta value Set Artist field in ID3 tag " << std::endl;
00230 std::cout << " -tA value Set Album field in ID3 tag " << std::endl;
00231 std::cout << " -tn value Set Track Number in ID3 tag " << std::endl;
00232 std::cout << " -ty value Set Year field in ID3 tag " << std::endl;
00233 std::cout << " -tc value Set Comment field in ID3 tag " << std::endl;
00234 std::cout << " -tg value Set Genre field in ID3 tag " << std::endl;
00235 std::cout << " (only standard ID3 genres can be used) " << std::endl;
00236 }