Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2006 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 "../common_source.h" 00020 #include "WavFileSink.h" 00021 00022 using namespace std; 00023 using namespace Marsyas; 00024 00025 WavFileSink::WavFileSink(mrs_string name):AbsSoundFileSink("WavFileSink",name) 00026 { 00027 //type_ = "WavFileSink"; 00028 //name_ = name; 00029 00030 sfp_ = NULL; 00031 sdata_ = NULL; 00032 cdata_ = NULL; 00033 00034 addControls(); 00035 } 00036 00037 WavFileSink::~WavFileSink() 00038 { 00039 delete [] sdata_; 00040 delete [] cdata_; 00041 if (sfp_) fclose(sfp_); 00042 } 00043 00044 MarSystem* 00045 WavFileSink::clone() const 00046 { 00047 return new WavFileSink(*this); 00048 } 00049 00050 void 00051 WavFileSink::addControls() 00052 { 00053 addctrl("mrs_string/filename", "default"); 00054 setctrlState("mrs_string/filename", true); 00055 00056 // lossy encoding specific controls 00057 addctrl("mrs_natural/bitrate", 128); 00058 setctrlState("mrs_natural/bitrate", true); 00059 addctrl("mrs_natural/encodingQuality", 2); 00060 setctrlState("mrs_natural/encodingQuality", true); 00061 addctrl("mrs_string/id3tags", "id3tags"); // 1: track one O Blues genreopen 00062 setctrlState("mrs_string/id3tags", true); 00063 00064 } 00065 00066 bool 00067 WavFileSink::checkExtension(mrs_string filename) 00068 { 00069 FileName fn(filename); 00070 mrs_string wavext = "wav"; 00071 mrs_string sndext = "snd"; 00072 00073 if (fn.ext() == wavext) 00074 return true; 00075 else 00076 return false; 00077 } 00078 00079 void 00080 WavFileSink::myUpdate(MarControlPtr sender) 00081 { 00082 (void) sender; //suppress warning of unused parameter(s) 00083 MRSDIAG("WavFileSink::myUpdate"); 00084 00085 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples")); 00086 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations")); 00087 setctrl("mrs_real/osrate", getctrl("mrs_real/israte")); 00088 00089 nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00090 00091 delete [] sdata_; 00092 delete [] cdata_; 00093 00094 sdata_ = new short[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_]; 00095 cdata_ = new unsigned char[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_]; 00096 00097 filename_ = getctrl("mrs_string/filename")->to<mrs_string>(); 00098 } 00099 00100 void 00101 WavFileSink::putHeader(mrs_string filename) 00102 { 00103 mrs_natural nChannels = (mrs_natural)getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00104 sfp_ = fopen(filename.c_str(), "wb"); 00105 00106 written_ = 0; 00107 00108 /* prepare header */ 00109 hdr_.riff[0] = 'R'; 00110 hdr_.riff[1] = 'I'; 00111 hdr_.riff[2] = 'F'; 00112 hdr_.riff[3] = 'F'; 00113 00114 hdr_.file_size = 44; 00115 00116 hdr_.wave[0] = 'W'; 00117 hdr_.wave[1] = 'A'; 00118 hdr_.wave[2] = 'V'; 00119 hdr_.wave[3] = 'E'; 00120 00121 hdr_.fmt[0] = 'f'; 00122 hdr_.fmt[1] = 'm'; 00123 hdr_.fmt[2] = 't'; 00124 hdr_.fmt[3] = ' '; 00125 00126 #if defined(MARSYAS_BIGENDIAN) 00127 hdr_.chunk_size = ByteSwapLong(16); 00128 hdr_.format_tag = ByteSwapShort(1); 00129 hdr_.num_chans = ByteSwapShort((signed short)nChannels); 00130 hdr_.sample_rate = ByteSwapLong((mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>()); 00131 hdr_.bytes_per_sec = ByteSwapLong(hdr_.sample_rate * 2); 00132 hdr_.bytes_per_samp = ByteSwapShort(2); 00133 hdr_.bits_per_samp = ByteSwapShort(16); 00134 hdr_.data_length = ByteSwapLong(0); 00135 #else 00136 hdr_.chunk_size = 16; 00137 hdr_.format_tag = 1; 00138 hdr_.num_chans = (signed short)nChannels; 00139 hdr_.sample_rate = (mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>(); 00140 hdr_.bytes_per_sec = hdr_.sample_rate * 2; 00141 hdr_.bytes_per_samp = 2; 00142 hdr_.bits_per_samp = 16; 00143 hdr_.data_length = 0; 00144 #endif 00145 00146 hdr_.data[0] = 'd'; 00147 hdr_.data[1] = 'a'; 00148 hdr_.data[2] = 't'; 00149 hdr_.data[3] = 'a'; 00150 00151 fwrite(&hdr_, 4, 11, sfp_); 00152 00153 sfp_begin_ = ftell(sfp_); 00154 } 00155 00156 unsigned long 00157 WavFileSink::ByteSwapLong(unsigned long nLongNumber) 00158 { 00159 return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+ 00160 ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24)); 00161 } 00162 00163 unsigned short 00164 WavFileSink::ByteSwapShort (unsigned short nValue) 00165 { 00166 return (static_cast<unsigned short>((nValue & 0xff00) >> 8) | 00167 static_cast<unsigned short>((nValue & 0xff) << 8)); 00168 } 00169 00170 void 00171 WavFileSink::putLinear16Swap(realvec& slice) 00172 { 00173 for (mrs_natural c=0; c < nChannels_; ++c) 00174 for (mrs_natural t=0; t < inSamples_; t++) 00175 { 00176 #if defined(MARSYAS_BIGENDIAN) 00177 sdata_[t*nChannels_ + c] = ByteSwapShort((short)(slice(c,t) * PCM_MAXSHRT)); 00178 #else 00179 sdata_[t*nChannels_ + c] = (short)(slice(c,t) * PCM_MAXSHRT); 00180 #endif 00181 } 00182 00183 if ((mrs_natural)fwrite(sdata_, sizeof(short), nChannels_ * inSamples_, sfp_) != nChannels_ * inSamples_) 00184 { 00185 MRSERR("Problem: could not write window to file " + filename_); 00186 } 00187 } 00188 00189 void 00190 WavFileSink::myProcess(realvec& in, realvec& out) 00191 { 00192 mrs_natural o,t; 00193 00194 // copy input to output 00195 for (o=0; o < inObservations_; o++) 00196 for (t=0; t < inSamples_; t++) 00197 { 00198 out(o,t) = in(o,t); 00199 } 00200 00201 long fileSize; 00202 fpos_ = ftell(sfp_); 00203 00204 // jump to start and write data size 00205 fseek(sfp_, 40, SEEK_SET); 00206 written_ += inSamples_; 00207 fileSize = (written_ * 2 * nChannels_); 00208 #if defined(MARSYAS_BIGENDIAN) 00209 fileSize = ByteSwapLong(fileSize); 00210 #endif 00211 00212 fwrite(&fileSize, 4, 1, sfp_); 00213 fseek(sfp_, fpos_, SEEK_SET); 00214 00215 putLinear16Swap(in); 00216 } 00217 00218 00219 00220 00221 00222 00223 00224 00225 00226 00227 00228 00229 00230 00231 00232 00233 00234