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