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;
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
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
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
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