7

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

đang

Cá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.

+0

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. –

+0

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. –

+2

Đâ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

Trả lời

7

Quảng cáo chiêu hàng không giống với bin tần số cao điểm (đó là những gì FFT trong khung tăng tốc có thể cung cấp trực tiếp cho bạn). Vì vậy, bất kỳ đầu dò tần số cao điểm nào cũng sẽ không đáng tin cậy đối với ước lượng độ cao. Một bộ lọc low-pass sẽ không giúp ích khi nốt nhạc bị thiếu hoặc rất yếu cơ bản (phổ biến trong một số âm thanh, giọng nói piano và guitar) và/hoặc rất nhiều âm bội mạnh mẽ trong quang phổ của nó.

Nhìn vào dải phổ rộng hoặc quang phổ của âm thanh của bạn và bạn sẽ thấy sự cố.

Các phương pháp khác thường là cần thiết để ước tính đáng tin cậy hơn về âm nhạc. Một số trong số này bao gồm các phương pháp tự tương quan (AMDF, ASDF), phân tích Cepstrum/Cepstral, phổ sản phẩm hài, bộ khuếch đại giai đoạn và/hoặc các thuật toán tổng hợp như RAPT (Thuật toán mạnh mẽ cho Pitch Tracking) và YAAPT. Một FFT hữu ích như chỉ là một phần phụ của một số phương pháp trên.

+0

Cảm ơn @ hotpaw2. Tôi sẽ phải đào sâu vào một số kỹ thuật bạn liệt kê ở đây. Cảm ơn những lời đề nghị. –

+0

Tài liệu tham khảo để mô tả một số phương pháp ước tính cao độ khác có trên blog của tôi: http://www.nicholson.com/rhn/dsp.html#1 – hotpaw2

3

Ít nhất bạn cần áp dụng window function cho dữ liệu miền thời gian của mình, trước khi tính toán FFT. Nếu không có bước này, phổ công suất sẽ chứa các đồ tạo tác (xem: spectral leakage) sẽ ảnh hưởng đến các nỗ lực của bạn trong việc trích xuất thông tin về độ cao.

Một cửa sổ đơn giản Hann (aka Hanning) là đủ.

+2

Câu trả lời hay và hình đại diện đẹp: D – jarryd

+0

Không thể thực sự đồng ý với nhận xét này. Bạn cần phải áp dụng một bộ lọc cửa sổ _before_ bạn lấy mẫu tín hiệu analog của bạn. Sau khi lấy mẫu (ví dụ: một khi được ghi qua micrô hoặc dưới dạng WAV), bạn không cần lọc bất kỳ thứ gì - trừ khi bạn đang tìm kiếm một hiệu ứng khác –

+0

@ZeJibe: Tôi nghĩ có lẽ bạn đang bối rối giữa việc áp dụng [ chức năng cửa sổ] (https://en.wikipedia.org/wiki/Window_function) và sử dụng [bộ lọc chống răng cưa] (https://en.wikipedia.org/wiki/Anti-aliasing_filter)? –

1

Tần suất mẫu của bạn và khối là gì? Low E là khoảng 80 Hz, vì vậy bạn cần đảm bảo rằng khối chụp của bạn đủ dài để chụp nhiều chu kỳ ở tần số này. Điều này là do Biến đổi Fourier phân chia phổ tần số thành các thùng, mỗi một vài Hz rộng. Nếu bạn lấy mẫu ở 44.1 kHz và có một mẫu miền thời gian 1024 điểm, ví dụ, mỗi bin sẽ là 44100/1024 = 43,07 Hz rộng. Như vậy một E thấp sẽ nằm trong thùng thứ hai. Đối với một loạt các lý do (để làm với rò rỉ quang phổ và bản chất của các khối thời gian hữu hạn), thực tế nói bạn nên xem xét 3 hoặc 4 thùng dữ liệu đầu tiên trong kết quả FFT với sự nghi ngờ cực đoan.

Nếu bạn giảm tốc độ mẫu xuống 8 kHz, cùng một khối sẽ cho bạn các thùng rộng 7.8125 Hz. Bây giờ, E thấp sẽ nằm trong thùng thứ 10 hoặc thứ 11, tốt hơn nhiều. Bạn cũng có thể sử dụng blockize dài hơn.

Và như Paul R points out, bạn PHẢI sử dụng cửa sổ để giảm rò rỉ quang phổ.

+0

Tôi đã thử cả 22050 và 44100. Tôi cũng đã thử các khối 1024, 2048 và 4096 trong một bộ đệm tròn giúp lưu trữ dữ liệu của mỗi cuộc gọi lại cho đến khi tôi nhận được số lượng 'khối hóa'. Tôi hiểu ý tưởng rằng, với một khối cố định, tỷ lệ lấy mẫu thấp hơn sẽ cho tôi thùng rộng hơn một chút và làm cho nó dễ dàng hơn một chút để nghe mức E. thấpThật không may, những gì tôi nhận thấy là một khi tôi nhận được xuống đến khoảng 295 Hz, bộ chỉnh bắt đầu để đọc số như 883 và 901. Rất rất gần với bội số của 2 và 3 của giai điệu thực sự. –

+0

Tôi đang tạo nhạc chuông trên một chiếc iPhone khác mà tôi đã ngồi xung quanh. Tôi đã nhận thấy rằng khi tôi bật nó lên, và âm thanh thuần khiết của tôi bắt đầu phát ra âm thanh, bộ chỉnh sẽ mất giá trị chính xác mà nó đang hiển thị và bắt đầu đi vào các tần số khác --- không nhất thiết là bội số của 2 hoặc 3 của giai điệu cơ bản mà tôi đang tìm kiếm. –

+0

Kích thước khối dài hơn là khởi đầu tốt cho bất kỳ trình ước tính độ cao nào, nhưng đỉnh cao FFT vẫn không hoạt động đối với bất kỳ âm thanh nào có tần số cơ bản bị thiếu hoặc yếu (ngay cả khi tắt micrô). – hotpaw2

1

Chức năng phản hồi tần số của iPhone giảm xuống dưới 100 - 200 Hz (xem http://blog.faberacoustical.com/2009/ios/iphone/iphone-microphone-frequency-response-comparison/ để biết ví dụ).

Nếu bạn đang cố gắng phát hiện chế độ cơ bản của chuỗi đàn guitar thấp, micrô có thể hoạt động như một bộ lọc và chặn tần suất bạn quan tâm. Có một vài tùy chọn nếu bạn muốn sử dụng dữ liệu fft bạn có thể nhận được - bạn có thể hiển thị dữ liệu trong miền tần số xung quanh ghi chú mà bạn đang cố gắng phát hiện để tất cả những gì bạn có thể thấy là chế độ đầu tiên ngay cả khi nó có cường độ thấp hơn các chế độ cao hơn (tức là có chuyển đổi để điều chỉnh và đặt nó ở chế độ này).

Hoặc bạn có thể vượt qua thấp lọc dữ liệu âm thanh - bạn có thể thực hiện điều này trong miền thời gian hoặc thậm chí dễ dàng hơn vì bạn đã có dữ liệu miền tần số, trong miền tần số. Bộ lọc thông thấp của miền thời gian rất đơn giản là làm bộ lọc trung bình di chuyển theo thời gian. Bộ lọc thông thấp của miền tần số rất đơn giản là nhân các độ lệch fft của bạn với một vectơ với 1 trong dải tần số thấp và một đoạn đường nối tuyến tính (hoặc thậm chí là một bước) trong các tần số cao hơn.