Tôi đã triển khai dự án Pitch Detector của Demetri cho iPhone và chống lại hai vấn đề. 1) bất kỳ loại tạp âm nền nào gửi chuối đọc tần số và 2) âm thanh tần số thấp hơn không được chiếu chính xác. Tôi cố gắng để điều chỉnh guitar của tôi và trong khi các dây cao làm việc - tuner không thể phân biệt một cách chính xác các E. thấpFFT trên iPhone để bỏ qua tạp âm nền và tìm các nốt thấp hơn
đangCác Pitch Detection tọa lạc tại RIOInterface.mm và đi một cái gì đó như thế này ...
// get the data
AudioUnitRender(...);
// convert int16 to float
Convert(...);
// divide the signal into even-odd configuration
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2);
// apply the fft
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
// convert split real form to split vector
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2);
Demetri sau đó tiếp tục xác định tần suất 'thống trị' như sau:
float dominantFrequency = 0;
int bin = -1;
for (int i=0; i<n; i+=2) {
float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]);
if (curFreq > dominantFrequency) {
dominantFrequency = curFreq;
bin = (i+1)/2;
}
}
memset(outputBuffer, 0, n*sizeof(SInt16));
// Update the UI with our newly acquired frequency value.
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)];
để bắt đầu, tôi tin rằng tôi cần phải áp dụng một bộ lọc thông thấp ... nhưng tôi không phải là một chuyên gia FFT và không đảm bảo chính xác vị trí hoặc cách thực hiện điều đó so với dữ liệu được trả về từ hàm vDSP S. Tôi cũng không chắc chắn làm thế nào để cải thiện độ chính xác của mã trong các tần số thấp hơn. Dường như có các thuật toán khác để xác định tần số chiếm ưu thế - nhưng một lần nữa, tìm kiếm một cú đá đúng hướng khi sử dụng dữ liệu được trả về bởi khung tăng tốc của Apple.
CẬP NHẬT:
Khuôn khổ tăng tốc thực sự có một số chức năng cửa sổ. Tôi thiết lập một cửa sổ cơ bản như thế này
windowSize = maxFrames;
transferBuffer = (float*)malloc(sizeof(float)*windowSize);
window = (float*)malloc(sizeof(float)*windowSize);
memset(window, 0, sizeof(float)*windowSize);
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM);
mà tôi sau đó áp dụng bằng cách chèn
vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize);
trước khi chức năng vDSP_ctoz. Tôi sau đó thay đổi phần còn lại của mã để sử dụng 'transferBuffer' thay vì outputBuffer ... nhưng cho đến nay, đã không nhận thấy bất kỳ thay đổi đáng kể trong dự đoán sân cuối cùng.
hai điều tôi nhớ khi chơi với công cụ này vài năm trở lại: bạn có thể đặt mức squelch cho âm nền chỉ bằng cách trừ dữ liệu đầu vào thô từ số tiền định trước (bạn có thể đoán ngay bây giờ) trong một thuật toán tốt), đặt bất kỳ thứ gì dưới 0 đến 0 và tần số thấp hơn, vì một lý do nào đó tôi không thể nhớ, không đăng ký lớn hơn, vì vậy bạn cần phải tăng quy mô tần số thấp theo cấp số nhân trước khi so sánh đến tần số chi phối cao hơn. –
Bạn dường như không áp dụng một chức năng cửa sổ phù hợp trước khi FFT của bạn, do đó, sẽ có rất nhiều đồ tạo tác trong quang phổ điện mà có lẽ sẽ gây rối lên bất kỳ loại nỗ lực phát hiện pitch. –
Đây là câu hỏi gần như trùng lặp với câu trả lời tương tự: http://stackoverflow.com/questions/4227420/matlab-missing-fundamental-from-an-fft – hotpaw2