D:/work/code_by/Wave/pitchlib.cpp

查看本檔案說明文件.
00001 #include <math.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 
00005 static const double LOG2 = 0.69314718;
00006 
00007 float freqToSmtn(float freq)
00008 {
00009   return freq <= 0.0f? 0.0f : 69.0 + 12.0 * log(freq / 440.0) / LOG2;
00010 }
00011 
00012 float smtnToFreq(int smtn)
00013 {
00014   return 440.0 * pow(2.0, (smtn - 69) / 12.0);
00015 }
00016 
00017 static int round(float f)
00018 {
00019   return floor(f + 0.5);
00020 }
00021 
00022 static float frameFreq(int *frame, int frameSize, int sampleRate)
00023 {
00024   int i, j, t, sum, threshold;
00025   int *vec;
00026   int minIndex[2];
00027 
00028   for (i = 0, j = 0; i < frameSize; i++)
00029     j += abs(frame[i]);
00030   if (j < frameSize * 3)  //音量太小
00031     return 0.0f;
00032 
00033   vec = new int[frameSize];
00034   t = sampleRate / 1047;  //假設pitch不超過84
00035   for (i = t - 1, threshold = -1; i < frameSize; i++)
00036   {
00037     for (j = frameSize - i - 1, sum = 0; j >= 0; j--)
00038       sum += abs(frame[j] - frame[j + i]);
00039     vec[i] = sum;
00040     if (sum > threshold)
00041       threshold = sum;
00042   }
00043   threshold /= 4;
00044 
00045   for (i = t, j = 0; i < frameSize - 1; i++)
00046     if (vec[i - 1] >= vec[i] && vec[i] < vec[i + 1] && vec[i] <= threshold)
00047     {
00048       minIndex[j++] = i;
00049       if (j >= 2)
00050         break;
00051     }
00052   delete[] vec;
00053 
00054   if (j == 0)
00055     return 0.0f;
00056   if (j == 2)
00057     if (abs((minIndex[1] - minIndex[0]) * 10 / minIndex[0] - 10) > 1)
00058       return 0.0f;
00059 
00060   return (float)sampleRate / minIndex[0];
00061 }
00062 
00063 static float medianIgnore0(float *vec, int vecSize)
00064 {
00065   int i, j, k;
00066   float *vecbak;
00067   float tmp;
00068 
00069   if (vecSize == 0)
00070     return 0;
00071   if (vecSize == 1)
00072     return vec[0];
00073 
00074   vecbak = new float[vecSize];
00075   memcpy(vecbak, vec, vecSize * sizeof(float));
00076   for (i = 0; i < vecSize - 1; i++)
00077   {
00078     k = i;
00079     for (j = i + 1; j < vecSize; j++)
00080       if (vecbak[j] > vecbak[k])
00081         k = j;
00082     if (k != i)
00083     {
00084       tmp = vecbak[i];
00085       vecbak[i] = vecbak[k];
00086       vecbak[k] = tmp;
00087     }
00088   }
00089 
00090   for (i = vecSize - 1; i > 0; i--)
00091     if (vecbak[i] != 0.0f)
00092       break;
00093   tmp = vecbak[i >> 1];
00094   delete[] vecbak;
00095   return tmp;
00096 }
00097 
00098 static int medianIgnore0(int *vec, int vecSize)
00099 {
00100   int i, j, k, tmp;
00101   int *vecbak;
00102 
00103   if (vecSize == 0)
00104     return 0;
00105   if (vecSize == 1)
00106     return vec[0];
00107 
00108   vecbak = new int[vecSize];
00109   memcpy(vecbak, vec, vecSize * sizeof(int));
00110   for (i = 0; i < vecSize - 1; i++)
00111   {
00112     k = i;
00113     for (j = i + 1; j < vecSize; j++)
00114       if (vecbak[j] > vecbak[k])
00115         k = j;
00116     if (k != i)
00117     {
00118       tmp = vecbak[i];
00119       vecbak[i] = vecbak[k];
00120       vecbak[k] = tmp;
00121     }
00122   }
00123 
00124   for (i = vecSize - 1; i > 0; i--)
00125     if (vecbak[i] != 0)
00126       break;
00127   tmp = vecbak[i >> 1];
00128   delete[] vecbak;
00129   return tmp;
00130 }
00131 
00132 void processWave(int *wave, int waveSize)
00133 {
00134   int i, mean;
00135 
00136   if (waveSize == 0)
00137     return;
00138 
00139   for (i = 0, mean = 0; i < waveSize; i++)
00140     mean += wave[i];
00141   mean /= waveSize;
00142   if (mean != 0)
00143     for (i = 0; i < waveSize; i++)
00144       wave[i] -= mean;
00145 }
00146 
00147 int waveToPitch(int *wave, int waveSize, int sampleRate, int pitchRate, float *&fpitch, int *used)
00148 {
00149   int i, pitchSize;
00150   int *frame, frameSize, frameStep;
00151 
00152   frameSize = sampleRate / 20;
00153   frameStep = sampleRate / pitchRate;
00154   pitchSize = (waveSize - frameSize) / frameStep;
00155   if (pitchSize <= 0)
00156   {
00157     if (used != NULL)
00158       *used = 0;
00159     return 0;
00160   }
00161   if (used != NULL)
00162     *used = pitchSize * frameStep;
00163 
00164   if (fpitch == NULL)
00165     fpitch = new float[pitchSize];
00166   for (i = 0, frame = wave; i < pitchSize; i++, frame += frameStep)
00167     fpitch[i] = freqToSmtn(frameFreq(frame, frameSize, sampleRate));
00168 
00169   return pitchSize;
00170 }
00171 
00172 void smoothPitch(float *fpitch, int pitchSize, int rate)
00173 {
00174   int i, w;
00175   float *pitchbak;
00176 
00177   if (pitchSize < rate)
00178     return;
00179 
00180   pitchbak = new float[pitchSize];
00181   memcpy(pitchbak, fpitch, pitchSize * sizeof(float));
00182 
00183   w = rate >> 1;
00184   fpitch[0] = medianIgnore0(pitchbak, w);
00185   for (i = 1; i < w; i++)
00186   {
00187     fpitch[i] = medianIgnore0(pitchbak, (i << 1) + 1);
00188     if (fabs(fpitch[i] - fpitch[i - 1]) < 1.0f)
00189       fpitch[i] = fpitch[i - 1];
00190     else if (fabs(fpitch[i] - fpitch[i + 1]) >= 1.0f)
00191       fpitch[i] = fpitch[i - 1];
00192   }
00193   for (; i < pitchSize - w; i++)
00194   {
00195     fpitch[i] = medianIgnore0(pitchbak + i - w, rate);
00196     if (fabs(fpitch[i] - fpitch[i - 1]) < 1.0f)
00197       fpitch[i] = fpitch[i - 1];
00198     else if (fabs(fpitch[i] - fpitch[i + 1]) >= 1.0f)
00199       fpitch[i] = fpitch[i - 1];
00200   }
00201   for (; i < pitchSize - 1; i++)
00202   {
00203     fpitch[i] = medianIgnore0(pitchbak + (i << 1) - pitchSize + 1, ((pitchSize - i) << 1) - 1);
00204     if (fabs(fpitch[i] - fpitch[i - 1]) < 1.0f)
00205       fpitch[i] = fpitch[i - 1];
00206   }
00207   fpitch[i] = medianIgnore0(pitchbak + pitchSize - w, w);
00208 
00209   delete[] pitchbak;
00210 }
00211 
00212 void correctPitch(float *fpitch, int pitchSize, int *pitch)
00213 {
00214   int i, j, s, shift;
00215   int whiteSum, maxWhiteSum;
00216   int white[] = {1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1};
00217 
00218   for (j = shift = 6 * 10, maxWhiteSum = -1; j > -6 * 10; j--)
00219   {
00220     for (i = 0, whiteSum = 0; i < pitchSize; i++)
00221       if (fpitch[i] != 0.0f)
00222       {
00223         s = floor(fpitch[i] + (j + 5) / 10.0f);
00224         whiteSum += white[s % 12];  //白鍵數目和
00225       }
00226     if (whiteSum > maxWhiteSum)
00227     {
00228       maxWhiteSum = whiteSum;
00229       shift = j;
00230     }
00231   }
00232 
00233   //====================== from Roger
00234   for (i = 0; i < pitchSize; i++)
00235   {
00236     pitch[i] = fpitch[i] == 0.0f? 0 : floor(fpitch[i] + (shift + 5) / 10.0f);
00237     if (white[pitch[i] % 12] == 0)  //黑鍵要修正
00238       if (fpitch[i] + shift / 10.0f <= pitch[i])
00239         --pitch[i];
00240       else
00241         ++pitch[i];
00242   }
00243   //======================
00244 }
00253 void limitPitch(float *fpitch, int pitchSize, float minPitch, float maxPitch)
00254 {
00255   int i;
00256 
00257   for (i = 0; i < pitchSize; i++)
00258     if (fpitch[i] != 0.0f)
00259       if (fpitch[i] < minPitch)
00260         fpitch[i] = 0.0f;
00261       else if (fpitch[i] > maxPitch)
00262         fpitch[i] = 0.0f;
00263 }
00264 
00273 void limitPitch(int *pitch, int pitchSize, int minPitch, int maxPitch)
00274 {
00275   int i;
00276 
00277   for (i = 0; i < pitchSize; i++)
00278     if (pitch[i] != 0)
00279       if (pitch[i] < minPitch)
00280         pitch[i] = 0;
00281       else if (pitch[i] > maxPitch)
00282         pitch[i] = 0;
00283 }
00284 
00285 
00294 void trimPitch(float *pitch, int pitchSize, int &from, int &to)
00295 {
00296   for (from = 0; from < pitchSize; from++)
00297     if (pitch[from] != 0.0f)
00298       break;
00299   for (to = pitchSize - 1; to > from; to--)
00300     if (pitch[to] != 0.0f)
00301       break;
00302 }
00311 void trimPitch(int *pitch, int pitchSize, int &from, int &to)
00312 {
00313   for (from = 0; from < pitchSize; from++)
00314     if (pitch[from] != 0)
00315       break;
00316   for (to = pitchSize - 1; to > from; to--)
00317     if (pitch[to] != 0)
00318       break;
00319 }
00320 
00321 int stairPitch(int *pitch, int pitchSize, int pitchRate, int tempo, int beatsPerMeasure)
00322 {
00323   int i, from, to, m, count;
00324   float f;
00325 
00326   if (pitchSize == 0)
00327     return 0;
00328 
00329   count = pitch[0] == 0? 0 : -1;
00330   to = 0;
00331   while (to < pitchSize)
00332   {
00333     for (from = to; from < pitchSize; from++)
00334       if (pitch[from] != 0)
00335         break;
00336     if (from == pitchSize)
00337     {
00338       ++count;
00339       break;
00340     }
00341     for (to = from + 1; to < pitchSize; to++)
00342       if (pitch[to] == 0)
00343         break;
00344 
00345     m = to - from > 0? medianIgnore0(pitch + from, to - from) : 0;
00346     for (i = from; i < to; i++)
00347       pitch[i] = m;
00348     if (m != 0)
00349       count += 2;
00350   }
00351 
00352   /*//======================  //from khair
00353   int pitchPerMeasure = pitchRate * beatsPerMeasure * 60 / tempo;
00354   for (i = 0; i < pitchSize; i++)
00355   {
00356     m = pitch[i] % 12;
00357     if (m == 1 || m == 3 || m == 6 || m == 8 || m == 10)  //黑鍵,要修正
00358     {
00359       from = i / pitchPerMeasure * pitchPerMeasure;
00360       to = from + pitchPerMeasure - 1;
00361       if (to >= pitchSize)
00362         break;
00363 
00364       f = i == from? 0.0f : (float)(pitch[i] - pitch[from]) / (i - from) - (float)(pitch[to] - pitch[from]) / (to - from);
00365       if (f > 0)
00366         --pitch[i];
00367       else if (f < 0)
00368         ++pitch[i];
00369       else
00370       {
00371         f = (float)(pitch[to] - pitch[from]) / (to - from);
00372         if (f >= 0)
00373           ++pitch[i];
00374         else
00375           --pitch[i];
00376       }
00377     }
00378   }
00379   //======================*/
00380 
00381   return count;
00382 }
00383 
00384 int pitchToMidi(int *pitch, int pitchSize, int *midi)
00385 {
00386   int i, from, d;
00387   int midiSize;
00388 
00389   midiSize = from = 0;
00390   for (i = 0; i < pitchSize; i++)
00391     if (pitch[i] != 0)
00392       break;
00393   d = i;
00394   while (i < pitchSize)
00395   {
00396     for (from = i++; i < pitchSize; i++)
00397       if (pitch[i] == 0)
00398         break;
00399     for (++i; i < pitchSize; i++)
00400       if (pitch[i] != 0)
00401         break;
00402 
00403     midi[midiSize] = pitch[from];
00404     midi[midiSize + 1] = i - from + d;
00405     d = 0;
00406     midiSize += 2;
00407   }
00408 
00409   return midiSize;
00410 }
00411 

產生日期:Tue Jul 11 11:52:19 2006, 專案:cbmr, 產生器:  doxygen 1.4.7