00001 #include <map>
00002 #include "Pitch2Chroma.h"
00003
00004 using std::ostringstream;
00005 using std::max;
00006 using std::min;
00007
00008 using namespace Marsyas;
00009
00010 Pitch2Chroma::Pitch2Chroma(mrs_string inName)
00011 :MarSystem("Pitch2Chroma",inName)
00012 {
00013 addControls();
00014 }
00015
00016 Pitch2Chroma::Pitch2Chroma(const Pitch2Chroma& inToCopy)
00017 :MarSystem(inToCopy)
00018 {
00019 ctrl_SampleRate_ = getctrl("mrs_real/SampleRate");
00020 ctrl_LowestPitch_ = getctrl("mrs_real/LowestPitch");
00021 ctrl_NotesPerOctave_ = getctrl("mrs_natural/NotesPerOctave");
00022 ctrl_NrOfNotes_ = getctrl("mrs_natural/NrOfNotes");
00023 ctrl_RefChromaIndex_ = getctrl("mrs_natural/RefChromaIndex_");
00024
00025 SampleRate_ = inToCopy.SampleRate_;
00026 LowestPitch_ = inToCopy.LowestPitch_;
00027 NotesPerOctave_ = inToCopy.NotesPerOctave_;
00028 NrOfNotes_ = inToCopy.NrOfNotes_;
00029 RefChromaIndex_ = inToCopy.RefChromaIndex_;
00030 }
00031
00032 Pitch2Chroma::~Pitch2Chroma(){}
00033
00034 MarSystem* Pitch2Chroma::clone() const
00035 {
00036 return new Pitch2Chroma(*this);
00037 }
00038
00039 void Pitch2Chroma::addControls()
00040 {
00041 addctrl("mrs_real/SampleRate",8000.,ctrl_SampleRate_);
00042 addctrl("mrs_real/LowestPitch",27.5,ctrl_LowestPitch_);
00043 addctrl("mrs_natural/NotesPerOctave",12,ctrl_NotesPerOctave_);
00044 addctrl("mrs_natural/NrOfNotes",88,ctrl_NrOfNotes_);
00045 addctrl("mrs_natural/RefChromaIndex_",6,ctrl_RefChromaIndex_);
00046
00047 ctrl_SampleRate_->setState(true);
00048 ctrl_LowestPitch_->setState(true);
00049 ctrl_NotesPerOctave_->setState(true);
00050 ctrl_NrOfNotes_->setState(true);
00051 ctrl_RefChromaIndex_->setState(true);
00052
00053 SampleRate_ = 8000.;
00054 LowestPitch_ = 27.5;
00055 NotesPerOctave_ = 12;
00056 NrOfNotes_ = 88;
00057 RefChromaIndex_ = 6;
00058 }
00059
00060 void Pitch2Chroma::myUpdate(MarControlPtr inSender)
00061 {
00062 MarSystem::myUpdate(inSender);
00063 ctrl_onObservations_->setValue(NotesPerOctave_,NOUPDATE);
00064
00065
00066 SampleRate_ = ctrl_SampleRate_->to<mrs_real>();
00067 LowestPitch_ = ctrl_LowestPitch_->to<mrs_real>();
00068 NotesPerOctave_ = ctrl_NotesPerOctave_->to<mrs_natural>();
00069 NrOfNotes_ = ctrl_NrOfNotes_->to<mrs_natural>();
00070 RefChromaIndex_ = ctrl_RefChromaIndex_->to<mrs_natural>();
00071
00072 UpdatePitchToNoteTransform();
00073 UpdateNoteToChromaTransform();
00074 }
00075
00076 void Pitch2Chroma::UpdatePitchToNoteTransform()
00077 {
00078
00079 PitchToNoteTransform_.create(NrOfNotes_,inObservations_);
00080 StartAndEndIndex_.create(NrOfNotes_,2);
00081
00082 mrs_real theLOGFc = LowestPitch_;
00083 mrs_real theLOGFStep = pow(2.,1./(mrs_real)NotesPerOctave_);
00084 mrs_real theLinFStep = SampleRate_/(2.f*(mrs_real)inObservations_);
00085 for (int i=0; i<NrOfNotes_; ++i)
00086 {
00087
00088 mrs_real theLOGFb = theLOGFc/sqrt(theLOGFStep);
00089 mrs_real theLOGFe = theLOGFc*sqrt(theLOGFStep);
00090
00091
00092 StartAndEndIndex_(i,0) = max((int)ceil(theLOGFb/theLinFStep),0);
00093 StartAndEndIndex_(i,1) = min((int)floor(theLOGFe/theLinFStep),(int)inObservations_-1);
00094
00095 for (int j=(mrs_natural)StartAndEndIndex_(i,0); j<=(mrs_natural)StartAndEndIndex_(i,1); j++)
00096 {
00097 double theBinFreq = (mrs_real)j*theLinFStep;
00098 if (theBinFreq <= theLOGFc)
00099
00100 PitchToNoteTransform_(i,j) = (theBinFreq-theLOGFb)/(theLOGFc-theLOGFb);
00101 else
00102
00103 PitchToNoteTransform_(i,j) = 1.-(theBinFreq-theLOGFc)/(theLOGFe-theLOGFc);
00104 }
00105
00106 theLOGFc *= theLOGFStep;
00107 }
00108 }
00109
00110 void Pitch2Chroma::UpdateNoteToChromaTransform()
00111 {
00112
00113 NoteToChromaTransform_.create(NotesPerOctave_,NrOfNotes_);
00114
00115 for (int i=0; i<NotesPerOctave_; ++i)
00116 for (int j=i; j<NrOfNotes_; j+=NotesPerOctave_)
00117 {
00118 int theChromaIndex = (7*i+RefChromaIndex_-1)%NotesPerOctave_;
00119 NoteToChromaTransform_(theChromaIndex,j) = 1.;
00120 }
00121 }
00122
00123 void Pitch2Chroma::myProcess(realvec& inVec, realvec& outVec)
00124 {
00125 mrs_natural t,o;
00126 outVec.setval(0.);
00127 for(o=0; o<onObservations_; o++)
00128 for(t=0; t<inSamples_; t++)
00129 for(int i=0; i<NrOfNotes_; ++i)
00130 for(int j=(mrs_natural)StartAndEndIndex_(i,0); j<=(mrs_natural)StartAndEndIndex_(i,1); j++)
00131 outVec(o,t) += NoteToChromaTransform_(o,i)*
00132 PitchToNoteTransform_(i,j)*inVec(j,t);
00133
00134 if (outVec.sum() != 0)
00135 outVec /= outVec.sum();
00136 }