Pitch PitchDetector::process2queue_average(float *input, unsigned int numberOfSamples) { static double sumFre = 0.0; static double sumAmp = 0.0; Pitch pitch = this->process(input, numberOfSamples); if (this->pitchQueue.size() > this->queueSize) { Pitch front_pitch = this->pitchQueue.front(); sumFre -= front_pitch.frequency; sumAmp -= front_pitch.amplitude; this->pitchQueue.pop(); this->pitchQueue.push(pitch); sumFre += pitch.frequency; sumAmp += pitch.amplitude; // 计算平均 this->bestPitch.frequency = sumFre/this->queueSize; this->bestPitch.amplitude = sumAmp/this->queueSize; this->bestPitch.key = 12 * log2(this->bestPitch.frequency / 127.09) + 28.5; this->bestPitch.octave = (this->bestPitch.key - 3.0) / 12 + 1; calStep(&this->bestPitch); this->bestPitch.stepString = calStep(this->bestPitch.frequency); } else { if (pitch.frequency > 0.0) { this->pitchQueue.push(pitch); sumFre += pitch.frequency; sumAmp += pitch.amplitude; } } if (this->bestPitch.amplitude == 0.0) { this->bestPitch = pitch; } return this->bestPitch; }
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; }
int main(void){ float *xyz,*vel; //ベルレ法を使うため、初期配置と初速度を定義 xyz=(float *)malloc(sizeof(float)*MOL_XYZ); vel=(float *)malloc(sizeof(float)*MOL_XYZ); init(xyz,vel); //vmd用に出力する show(xyz); //時間発展させる calStep(xyz,vel); free(xyz); free(vel); return 0; }