00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "AuFileSink.h"
00021
00022 using std::ostringstream;
00023 using namespace Marsyas;
00024
00025
00026
00027 #ifdef MARSYAS_WIN32
00028 #ifndef MARSYAS_CYGWIN
00029 typedef __int32 int32_t;
00030 #endif
00031 #else
00032 #include <stdint.h>
00033 #endif
00034
00035
00036
00037 struct Marsyas::snd_header
00038 {
00039 char pref[4];
00040 int32_t hdrLength;
00041 int32_t fileLength;
00042 int32_t mode;
00043 int32_t srate;
00044 int32_t channels;
00045 char comment[1024];
00046 };
00047
00048
00049
00050
00051
00052
00053 #define SND_MAGIC_NUM 0x2e736e64
00054
00055
00056
00057
00058
00059
00060
00061 #define SND_FORMAT_UNSPECIFIED 0
00062 #define SND_FORMAT_MULAW_8 1
00063 #define SND_FORMAT_LINEAR_8 2
00064 #define SND_FORMAT_LINEAR_16 3
00065 #define SND_FORMAT_LINEAR_24 4
00066 #define SND_FORMAT_LINEAR_32 5
00067 #define SND_FORMAT_FLOAT 6
00068
00069 AuFileSink::AuFileSink(mrs_string name):AbsSoundFileSink("AuFileSink",name)
00070 {
00071
00072
00073
00074 sfp_ = NULL;
00075 cdata_ = NULL;
00076 sdata_ = NULL;
00077 hdr_ = new snd_header;
00078
00079 addControls();
00080 }
00081
00082 AuFileSink::~AuFileSink()
00083 {
00084 delete [] sdata_;
00085 delete [] cdata_;
00086 delete hdr_;
00087 if (sfp_) fclose(sfp_);
00088 }
00089
00090
00091 AuFileSink::AuFileSink(const AuFileSink& a): AbsSoundFileSink(a)
00092 {
00093 hdr_ = new snd_header;
00094 }
00095
00096
00097
00098 MarSystem*
00099 AuFileSink::clone() const
00100 {
00101 return new AuFileSink(*this);
00102 }
00103
00104 void
00105 AuFileSink::addControls()
00106 {
00107 addctrl("mrs_string/filename", "daufile");
00108 setctrlState("mrs_string/filename", true);
00109
00110
00111 addctrl("mrs_natural/bitrate", 128);
00112 setctrlState("mrs_natural/bitrate", true);
00113 addctrl("mrs_natural/encodingQuality", 2);
00114 setctrlState("mrs_natural/encodingQuality", true);
00115 addctrl("mrs_string/id3tags", "noTitle|noArtist|noAlbum|1978|noComment|1|0");
00116 setctrlState("mrs_string/id3tags", true);
00117
00118 }
00119
00120 bool
00121 AuFileSink::checkExtension(mrs_string filename)
00122 {
00123 FileName fn(filename);
00124 mrs_string auext = "au";
00125 mrs_string sndext = "snd";
00126
00127 if ((fn.ext() == auext) || (fn.ext() == sndext))
00128 return true;
00129 else
00130 return false;
00131 }
00132
00133 void
00134 AuFileSink::myUpdate(MarControlPtr sender)
00135 {
00136 (void) sender;
00137 MRSDIAG("AudioFileSink::myUpdate");
00138 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00139 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations"));
00140 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00141
00142 nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00143
00144 delete [] sdata_;
00145 delete [] cdata_;
00146
00147 sdata_ = new short[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_];
00148 cdata_ = new unsigned char[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_];
00149
00150 filename_ = getctrl("mrs_string/filename")->to<mrs_string>();
00151 }
00152
00153 void
00154 AuFileSink::putHeader(mrs_string filename)
00155 {
00156 mrs_natural nChannels = (mrs_natural)getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00157
00158 written_ = 0;
00159 const char *comment = "MARSYAS 2001, George Tzanetakis.\n";
00160 mrs_natural commentSize = strlen(comment);
00161 sfp_ = fopen(filename.c_str(), "wb");
00162 hdr_->pref[0] = '.';
00163 hdr_->pref[1] = 's';
00164 hdr_->pref[2] = 'n';
00165 hdr_->pref[3] = 'd';
00166
00167 #if defined(MARSYAS_BIGENDIAN)
00168 hdr_->hdrLength = 24 + commentSize;
00169 hdr_->fileLength = 0;
00170 hdr_->mode = SND_FORMAT_LINEAR_16;
00171 hdr_->srate = (mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>();
00172 hdr_->channels = nChannels;
00173 #else
00174 hdr_->hdrLength = ByteSwapLong(24 + (unsigned long)commentSize);
00175 hdr_->fileLength = ByteSwapLong(0);
00176 hdr_->mode = ByteSwapLong(SND_FORMAT_LINEAR_16);
00177 hdr_->srate = ByteSwapLong((mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>());
00178 hdr_->channels = ByteSwapLong(nChannels);
00179 #endif
00180
00181 fwrite(hdr_, 24, 1, sfp_);
00182
00183 fwrite(comment, commentSize, 1, sfp_);
00184 sfp_begin_ = ftell(sfp_);
00185 }
00186
00187 unsigned long
00188 AuFileSink::ByteSwapLong(unsigned long nLongNumber)
00189 {
00190 return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+
00191 ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24));
00192 }
00193
00194 unsigned short
00195 AuFileSink::ByteSwapShort (unsigned short nValue)
00196 {
00197 return (((nValue>> 8)) | (nValue << 8));
00198 }
00199
00200 void
00201 AuFileSink::putLinear16(realvec& slice)
00202 {
00203 mrs_natural c,t;
00204 for (c=0; c < nChannels_; ++c)
00205 for (t=0; t < inSamples_; t++)
00206 {
00207 #if defined(MARSYAS_BIGENDIAN)
00208 sdata_[t*nChannels_ + c] = (short)(slice(c,t) * PCM_MAXSHRT);
00209 #else
00210 sdata_[t*nChannels_ + c] = ByteSwapShort((short)(slice(c,t) * PCM_MAXSHRT));
00211 #endif
00212 }
00213
00214 if ((mrs_natural)fwrite(sdata_, sizeof(short), nChannels_ * inSamples_, sfp_) != nChannels_ * inSamples_)
00215 {
00216 MRSWARN("Problem: could not write window to file" + filename_);
00217 }
00218 }
00219
00220 void
00221 AuFileSink::myProcess(realvec& in, realvec& out)
00222 {
00223 mrs_natural t,o;
00224
00225
00226
00227 for (o=0; o < inObservations_; o++)
00228 for (t=0; t < inSamples_; t++)
00229 {
00230 if (in(o,t) > 1.0)
00231 {
00232 MRSWARN("AuFileSink::Value out of range > 1.0");
00233 }
00234 if (in(o,t) < -1.0)
00235 {
00236 MRSWARN("AuFileSink::Value out of range < -1.0");
00237 }
00238 out(o,t) = in(o,t);
00239 }
00240
00241 long fileSize;
00242 fpos_ = ftell(sfp_);
00243 fseek(sfp_, 8, SEEK_SET);
00244 written_ += inSamples_;
00245 #if defined(MARSYAS_BIGENDIAN)
00246 fileSize = (written_ * 2 * nChannels_);
00247 #else
00248 fileSize = ByteSwapLong(written_ * 2 * nChannels_);
00249 #endif
00250
00251 fwrite(&fileSize, 4, 1, sfp_);
00252 fseek(sfp_, fpos_, SEEK_SET);
00253
00254 putLinear16(in);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271