Pitch PitchDetector::process(float *input, unsigned int numberOfSamples) { assert(this->numberOfSamples==numberOfSamples); int n = numberOfSamples; float *originalReal = this->FFTBuffer; // 1.1.时域上加窗 vDSP_vmul(input, 1, this->windowFunc, 1, originalReal, 1, n); // 分前后加窗没什么不一样啊 // vDSP_vmul(input, 1, this->windowFunc, 1, originalReal+(n/2), 1, n/2); // vDSP_vmul(input+(n/2), 1, this->windowFunc+(n/2), 1, originalReal, 1, n/2); // 2.拆成复数形似{1+2i, 3+4i, ..., 1023+1024i} 原始数组可以认为是(COMPLEX*)交错存储 现在拆成COMPLEX_SPLIT非交错(分轨式)存储 vDSP_ctoz((COMPLEX*)originalReal, 2, &this->A, 1, n/2); // 读取originalReal以2的步长塞进A里面 // // 3.fft变换的预设 float originalRealInLog2 = log2f(n); // FFTSetup setupReal = vDSP_create_fftsetup(originalRealInLog2, FFT_RADIX2); // 4.傅里叶变换 vDSP_fft_zrip(this->setupReal, &this->A, 1, originalRealInLog2, FFT_FORWARD); // 5.转换成能量值 vDSP_zvabs(&this->A, 1, this->magnitudes, 1, n/2); Float32 one = 1; vDSP_vdbcon(this->magnitudes, 1, &one, this->magnitudes, 1, n/2, 0); // 6.获取基频f0 float maxValue; vDSP_Length index; vDSP_maxvi(this->magnitudes, 1, &maxValue, &index, n/2); // 6.1.微调参数 double alpha = this->magnitudes[index - 1]; double beta = this->magnitudes[index]; double gamma = this->magnitudes[index + 1]; double p = 0.5 * (alpha - gamma) / (alpha - 2 * beta + gamma); // 7.转换为频率 indexHZ = index * (SampleRate / (n/2)) float indexHZ = (index+p) * ((this->sampleRate*1.0) / n); // 8.乐理信息生成 Pitch pitch; pitch.frequency = indexHZ; pitch.amplitude = beta; pitch.key = 12 * log2(indexHZ / 127.09) + 28.5; pitch.octave = (pitch.key - 3.0) / 12 + 1; calStep(&pitch); pitch.stepString = calStep(indexHZ); return pitch; }
Error_t VectorMaxVI(float* value, unsigned* index, const float* src, unsigned length) { #ifdef __APPLE__ // Use the Accelerate framework if we have it vDSP_maxvi(src, 1, value, (unsigned long*)index, length); #else float res = FLT_MIN; for (unsigned i = 0; i < length; ++i) { if (src[i] > res) { *value = res = src[i]; *index = i; } } #endif return NOERR; }
uint_t fvec_max_elem (fvec_t * s) { #ifndef HAVE_ACCELERATE uint_t j, pos = 0; smpl_t tmp = 0.0; for (j = 0; j < s->length; j++) { pos = (tmp > s->data[j]) ? pos : j; tmp = (tmp > s->data[j]) ? tmp : s->data[j]; } #else smpl_t tmp = 0.; uint_t pos = 0.; #if !HAVE_AUBIO_DOUBLE vDSP_maxvi(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length); #else vDSP_maxviD(s->data, 1, &tmp, (vDSP_Length *)&pos, s->length); #endif #endif return pos; }