00001 #include "TranscriberExtract.h"
00002 namespace Marsyas
00003 {
00004
00005
00006
00007 TranscriberExtract::TranscriberExtract()
00008 {
00009 }
00010
00011 TranscriberExtract::~TranscriberExtract()
00012 {
00013 }
00014
00015 mrs_real TranscriberExtract::addFileSource(MarSystem* net, const std::string infile)
00016 {
00017 if (infile == EMPTYSTRING)
00018 {
00019 MRSERR("Please specify a sound file.");
00020 return 0;
00021 }
00022 net->addMarSystem(mng.create("SoundFileSource", "src"));
00023 net->updControl("SoundFileSource/src/mrs_string/filename", infile);
00024 net->linkControl("mrs_bool/hasData",
00025 "SoundFileSource/src/mrs_bool/hasData");
00026 return net->getctrl("SoundFileSource/src/mrs_real/osrate")->to<mrs_real>();
00027 }
00028
00029
00030 MarSystem*
00031 TranscriberExtract::makePitchNet(const mrs_real srate, const mrs_real lowFreq, MarSystem* rvSink)
00032 {
00033 mrs_real highFreq = 5000.0;
00034
00035 MarSystem *net = mng.create("Series", "pitchNet");
00036 net->addMarSystem(mng.create("ShiftInput", "sfi"));
00037 net->addMarSystem(mng.create("PitchPraat", "pitch"));
00038 if (rvSink != NULL)
00039 net->addMarSystem(rvSink);
00040
00041
00042 net->updControl("PitchPraat/pitch/mrs_natural/lowSamples",
00043 hertz2samples(highFreq, srate) );
00044 net->updControl("PitchPraat/pitch/mrs_natural/highSamples",
00045 hertz2samples(lowFreq, srate) );
00046
00047
00048
00049 mrs_real windowSize = 3.0/lowFreq*srate;
00050 net->updControl("mrs_natural/inSamples", 512);
00051 net->updControl("ShiftInput/sfi/mrs_natural/winSize",
00052 powerOfTwo(windowSize));
00053
00054 return net;
00055 }
00056
00057 MarSystem* TranscriberExtract::makeAmplitudeNet(MarSystem* rvSink)
00058 {
00059 MarSystem *net = mng.create("Series", "amplitudeNet");
00060 net->addMarSystem(mng.create("ShiftInput", "sfiAmp"));
00061 net->addMarSystem(mng.create("Rms", "rms"));
00062 if (rvSink != NULL)
00063 net->addMarSystem(rvSink);
00064
00065 net->updControl("mrs_natural/inSamples", 512);
00066 net->updControl("ShiftInput/sfiAmp/mrs_natural/winSize", 512);
00067
00068 return net;
00069 }
00070
00071 void
00072 TranscriberExtract::getAllFromAudio(const std::string audioFilename, realvec&
00073 pitchList, realvec& ampList,
00074 realvec& boundaries)
00075 {
00076 MarSystem* pitchSink = mng.create("RealvecSink", "pitchSink");
00077 MarSystem* ampSink = mng.create("RealvecSink", "ampSink");
00078
00079 MarSystem* pnet = mng.create("Series", "pnet");
00080 mrs_real srate = addFileSource(pnet, audioFilename);
00081
00082
00083
00084
00085
00086 MarSystem* fanout = mng.create("Fanout", "fanout");
00087 fanout->addMarSystem(makePitchNet(srate, 100.0, pitchSink));
00088 fanout->addMarSystem(makeAmplitudeNet(ampSink));
00089 pnet->addMarSystem(fanout);
00090
00091 while ( pnet->getctrl("mrs_bool/hasData")->to<mrs_bool>() )
00092 pnet->tick();
00093
00094 pitchList = getPitchesFromRealvecSink(pitchSink, srate);
00095 ampList = getAmpsFromRealvecSink(ampSink);
00096 boundaries.create(2);
00097 boundaries(0) = 0;
00098 boundaries(1) = pitchList.getSize();
00099 delete pnet;
00100 }
00101
00102 realvec
00103 TranscriberExtract::getPitchesFromAudio(const std::string audioFilename)
00104 {
00105 mrs_real normalize = getNormalizingGain(audioFilename);
00106
00107 MarSystem* pnet = mng.create("Series", "pnet");
00108 mrs_real srate = addFileSource(pnet, audioFilename);
00109 pnet->addMarSystem(mng.create("Gain", "normalizing"));
00110 pnet->updControl("Gain/normalizing/mrs_real/gain",normalize);
00111 MarSystem* rvSink = mng.create("RealvecSink", "rvSink");
00112 pnet->addMarSystem(makePitchNet(srate, 100.0, rvSink));
00113
00114 while ( pnet->getctrl("mrs_bool/hasData")->to<mrs_bool>() )
00115 pnet->tick();
00116
00117 realvec pitchList = getPitchesFromRealvecSink(rvSink, srate);
00118 delete pnet;
00119 return pitchList;
00120 }
00121
00122 realvec
00123 TranscriberExtract::getAmpsFromAudio(const std::string audioFilename)
00124 {
00125 mrs_real normalize = getNormalizingGain(audioFilename);
00126
00127 MarSystem* pnet = mng.create("Series", "pnet");
00128 mrs_real srate;
00129 srate = addFileSource(pnet, audioFilename);
00130
00131 pnet->addMarSystem(mng.create("Gain", "normalizing"));
00132 pnet->updControl("Gain/normalizing/mrs_real/gain",normalize);
00133 MarSystem* rvSink = mng.create("RealvecSink", "rvSink");
00134 pnet->addMarSystem(makeAmplitudeNet(rvSink));
00135
00136 while ( pnet->getctrl("mrs_bool/hasData")->to<mrs_bool>() )
00137 pnet->tick();
00138
00139 realvec rmsList = getAmpsFromRealvecSink(rvSink);
00140 delete pnet;
00141
00142
00143 rmsList -= rmsList.minval();
00144 mrs_real maxRms = rmsList.maxval();
00145 if (maxRms != 0)
00146 rmsList /= maxRms;
00147 return rmsList;
00148 }
00149
00150 realvec
00151 TranscriberExtract::getPitchesFromRealvecSink(MarSystem* rvSink,
00152 const mrs_real srate)
00153 {
00154 realvec data = rvSink->getctrl("mrs_realvec/data")->to<mrs_realvec>();
00155 rvSink->updControl("mrs_bool/done", true);
00156
00157 realvec pitchList(data.getSize()/2);
00158 mrs_real pitchOutput;
00159 for (mrs_natural i=0; i<pitchList.getSize(); ++i)
00160 {
00161
00162
00163 pitchOutput = data(2*i+1);
00164 if (pitchOutput > 1)
00165 pitchList(i) = samples2hertz( pitchOutput, srate);
00166 else
00167 pitchList(i) = 0;
00168 }
00169 return pitchList;
00170 }
00171
00172 realvec
00173 TranscriberExtract::getAmpsFromRealvecSink(MarSystem* rvSink)
00174 {
00175 realvec data = rvSink->getctrl("mrs_realvec/data")->to<mrs_realvec>();
00176 rvSink->updControl("mrs_bool/done", true);
00177 realvec ampList(data.getSize());
00178 ampList = data;
00179 return ampList;
00180 }
00181
00182 void
00183 TranscriberExtract::toMidi(realvec& pitchList)
00184 {
00185 pitchList.apply( hertz2pitch );
00186 }
00187
00188 mrs_real
00189 TranscriberExtract::getNormalizingGain(const std::string audioFilename)
00190 {
00191 mrs_real maxVal = 0.0;
00192
00193 MarSystem* pnet = mng.create("Series", "pnet");
00194 addFileSource(pnet, audioFilename);
00195
00196 pnet->addMarSystem(mng.create("Gain", "null"));
00197
00198 while ( pnet->getctrl("mrs_bool/hasData")->to<mrs_bool>() )
00199 {
00200 pnet->tick();
00201 const realvec& processedData =
00202 pnet->getctrl("SoundFileSource/src/mrs_realvec/processedData")->to<mrs_realvec>();
00203 for (mrs_natural i=0; i< processedData.getSize(); ++i)
00204 {
00205 mrs_real val = fabs(processedData(i));
00206 if (val > maxVal)
00207 maxVal = val;
00208 }
00209 }
00210
00211 delete pnet;
00212 return 1.0/maxVal;
00213 }
00214
00215 }