00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.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
00028
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
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");
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;
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
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 (((nValue>> 8)) | (nValue << 8));
00167 }
00168
00169 void
00170 WavFileSink::putLinear16Swap(realvec& slice)
00171 {
00172 for (mrs_natural c=0; c < nChannels_; ++c)
00173 for (mrs_natural t=0; t < inSamples_; t++)
00174 {
00175 #if defined(MARSYAS_BIGENDIAN)
00176 sdata_[t*nChannels_ + c] = ByteSwapShort((short)(slice(c,t) * PCM_MAXSHRT));
00177 #else
00178 sdata_[t*nChannels_ + c] = (short)(slice(c,t) * PCM_MAXSHRT);
00179 #endif
00180 }
00181
00182 if ((mrs_natural)fwrite(sdata_, sizeof(short), nChannels_ * inSamples_, sfp_) != nChannels_ * inSamples_)
00183 {
00184 MRSERR("Problem: could not write window to file " + filename_);
00185 }
00186 }
00187
00188 void
00189 WavFileSink::myProcess(realvec& in, realvec& out)
00190 {
00191 mrs_natural o,t;
00192
00193
00194 for (o=0; o < inObservations_; o++)
00195 for (t=0; t < inSamples_; t++)
00196 {
00197 out(o,t) = in(o,t);
00198 }
00199
00200 long fileSize;
00201 fpos_ = ftell(sfp_);
00202
00203
00204 fseek(sfp_, 40, SEEK_SET);
00205 written_ += inSamples_;
00206 fileSize = (written_ * 2 * nChannels_);
00207 #if defined(MARSYAS_BIGENDIAN)
00208 fileSize = ByteSwapLong(fileSize);
00209 #endif
00210
00211 fwrite(&fileSize, 4, 1, sfp_);
00212 fseek(sfp_, fpos_, SEEK_SET);
00213
00214 putLinear16Swap(in);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233