Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2010 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include <marsyas/common_source.h> 00020 #include "MP3FileSink.h" 00021 00022 #include "lame/lame.h" 00023 00024 using std::ostringstream; 00025 using namespace Marsyas; 00026 00027 MP3FileSink::MP3FileSink(mrs_string name):AbsSoundFileSink("MP3FileSink",name) 00028 { 00029 //type_ = "MP3FileSink"; 00030 //name_ = name; 00031 gfp_ = NULL; 00032 sfp_ = NULL; 00033 leftpcm_ = NULL; 00034 rightpcm_ = NULL; 00035 00036 mp3Buffer_ = NULL; 00037 addControls(); 00038 } 00039 00040 MP3FileSink::~MP3FileSink() 00041 { 00042 00043 00044 if (sfp_) 00045 { 00046 mrs_natural encodeCheck = lame_encode_flush(gfp_, mp3Buffer_, 0); 00047 mrs_natural owrite = (int) fwrite(mp3Buffer_, 1, encodeCheck, sfp_); 00048 if (owrite != encodeCheck) { 00049 MRSWARN("Writing MP3 data to "+filename_+" failed."); 00050 } 00051 fclose(sfp_); 00052 } 00053 00054 00055 delete [] mp3Buffer_; 00056 delete [] leftpcm_; 00057 delete [] rightpcm_; 00058 } 00059 00060 MarSystem* 00061 MP3FileSink::clone() const 00062 { 00063 return new MP3FileSink(*this); 00064 } 00065 00066 void 00067 MP3FileSink::addControls() 00068 { 00069 addctrl("mrs_string/filename", "default"); 00070 setctrlState("mrs_string/filename", true); 00071 addctrl("mrs_natural/bitrate", 128); 00072 setctrlState("mrs_natural/bitrate", true); 00073 addctrl("mrs_natural/encodingQuality", 2); 00074 setctrlState("mrs_natural/encodingQuality", true); 00075 addctrl("mrs_string/id3tags", "noTitle|noArtist|noAlbum|1978|noComment|1|0"); // 1: track one O Blues genreopen 00076 setctrlState("mrs_string/filename", true); 00077 } 00078 00079 bool 00080 MP3FileSink::checkExtension(mrs_string filename) 00081 { 00082 FileName fn(filename); 00083 mrs_string mp3ext = "mp3"; 00084 00085 if (fn.ext() == mp3ext) 00086 return true; 00087 else 00088 return false; 00089 } 00090 00091 void 00092 MP3FileSink::myUpdate(MarControlPtr sender) 00093 { 00094 (void) sender; //suppress warning of unused parameter(s) 00095 MRSDIAG("MP3FileSink::myUpdate"); 00096 00097 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples")); 00098 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations")); 00099 setctrl("mrs_real/osrate", getctrl("mrs_real/israte")); 00100 00101 nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00102 00103 // initialize to default encoding parameters 00104 gfp_ = lame_init(); 00105 00106 mrs_natural lameNbChannels = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00107 delete [] mp3Buffer_; 00108 mrs_natural mp3BufferSize = (int) ceil(1.25*inSamples_ + 7200); 00109 mp3Buffer_ = new unsigned char[mp3BufferSize]; //[LAME_MAXMP3BUFFER]; 00110 delete [] leftpcm_; 00111 delete [] rightpcm_; 00112 leftpcm_ = new short[getctrl("mrs_natural/inSamples")->to<mrs_natural>()]; 00113 rightpcm_ = new short[getctrl("mrs_natural/inSamples")->to<mrs_natural>()]; 00114 00115 if (lameNbChannels>2) { 00116 MRSWARN("Lame can handle up to 2 channels. Only the first 2 observation vectors will be written."); 00117 lameNbChannels = 2; 00118 } 00119 if (lameNbChannels==1) 00120 lame_set_mode(gfp_, (MPEG_mode) 3); // mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono 00121 else 00122 lame_set_mode(gfp_, (MPEG_mode) 1); 00123 00124 lame_set_num_channels(gfp_,lameNbChannels); 00125 lame_set_in_samplerate(gfp_,(int) ceil(getctrl("mrs_real/israte")->to<mrs_real>())); 00126 lame_set_brate(gfp_,128); // ,(int) ceil(getctrl("mrs_natural/bitrate")->to<mrs_natural>()) 00127 lame_set_quality(gfp_,2); /* 2=high 5 = medium 7=low */ // ,(int) ceil(getctrl("mrs_natural/encodingQuality")->to<mrs_natural>()) 00128 00129 // split id3 string 00130 mrs_string id3tags = getctrl("mrs_string/id3tags")->to<mrs_string>(); 00131 mrs_natural pos=0; 00132 pos = id3tags.find("|", 0); 00133 id3tag_set_title(gfp_, id3tags.substr(0, pos).c_str()); 00134 id3tags = id3tags.substr(pos+1); 00135 pos = id3tags.find("|", 0); 00136 id3tag_set_artist(gfp_, id3tags.substr(0, pos).c_str()); 00137 id3tags = id3tags.substr(pos+1); 00138 pos = id3tags.find("|", 0); 00139 id3tag_set_album(gfp_, id3tags.substr(0, pos).c_str()); 00140 id3tags = id3tags.substr(pos+1); 00141 pos = id3tags.find("|", 0); 00142 id3tag_set_year(gfp_, id3tags.substr(0, pos).c_str()); 00143 id3tags = id3tags.substr(pos+1); 00144 pos = id3tags.find("|", 0); 00145 id3tag_set_comment(gfp_, id3tags.substr(0, pos).c_str()); 00146 id3tags = id3tags.substr(pos+1); 00147 pos = id3tags.find("|", 0); 00148 id3tag_set_track(gfp_, id3tags.substr(0, pos).c_str()); 00149 id3tags = id3tags.substr(pos+1); 00150 pos = id3tags.find("|", 0); 00151 id3tag_set_genre(gfp_, id3tags.substr(0, pos).c_str()); 00152 00153 int ret_code = lame_init_params(gfp_); 00154 if (ret_code == -1) 00155 MRSWARN("Initialization of the lame encoder failed."); 00156 00157 00158 00159 filename_ = getctrl("mrs_string/filename")->to<mrs_string>(); 00160 } 00161 00162 void 00163 MP3FileSink::putHeader(mrs_string filename) 00164 { 00165 sfp_ = fopen(filename.c_str(), "wb"); 00166 } 00167 00168 void 00169 MP3FileSink::myProcess(realvec& in, realvec& out) 00170 { 00171 00172 00173 mrs_natural t,o; 00174 00175 // copy input to output 00176 for (o=0; o < inObservations_; o++) 00177 for (t=0; t < inSamples_; t++) 00178 { 00179 out(o,t) = in(o,t); 00180 } 00181 00182 mrs_natural encodeCheck=-1; 00183 00184 // fill left buffer 00185 for (t=0; t < inSamples_; t++) 00186 leftpcm_[t] = (short)(in(0,t) * PCM_MAXSHRT); 00187 if (inObservations_>1) { 00188 // fill right buffer 00189 for (t=0; t < inSamples_; t++) 00190 rightpcm_[t] = (short)(in(1,t) * PCM_MAXSHRT); 00191 00192 encodeCheck = lame_encode_buffer(gfp_, 00193 leftpcm_, rightpcm_, 00194 inSamples_, mp3Buffer_, 0); 00195 } 00196 else 00197 encodeCheck = lame_encode_buffer(gfp_, 00198 leftpcm_, leftpcm_, 00199 inSamples_, mp3Buffer_,0); // [ML] 0 do not check for buffer size, should be sizeof(mp3Buffer_) but check fails 00200 00201 00202 /* was our output buffer big enough? */ 00203 if (encodeCheck < 0) { 00204 if (encodeCheck == -1) { 00205 MRSWARN("mp3 buffer is not big enough... \n"); 00206 } 00207 else 00208 MRSWARN("mp3 internal error"); 00209 } 00210 mrs_natural owrite = (int) fwrite(mp3Buffer_, 1, encodeCheck, sfp_); 00211 if (owrite != encodeCheck) { 00212 MRSWARN("Writing MP3 data to "+filename_+" failed."); 00213 } 00214 00215 00216 00217 } 00218 00219 00220 00221 00222 00223 00224 00225 00226 00227 00228 00229 00230 00231 00232 00233 00234 00235