ฉันจะใช้การเชื่อมโยงข้ามกันเพื่อพิสูจน์ไฟล์เสียงสองไฟล์ที่เหมือนกันได้อย่างไร


58

ฉันต้องทำ cross correlation ของไฟล์เสียงสองไฟล์เพื่อพิสูจน์ว่ามันคล้ายกัน ฉันใช้ FFT ของไฟล์เสียงสองไฟล์และมีค่าสเปกตรัมพลังงานในอาร์เรย์แยกต่างหาก

ฉันจะดำเนินการต่อเพื่อข้ามสหสัมพันธ์และพิสูจน์ว่าพวกเขาคล้ายกันได้อย่างไร มีวิธีที่ดีกว่าที่จะทำหรือไม่ แนวคิดพื้นฐานใด ๆ จะเป็นประโยชน์สำหรับฉันในการเรียนรู้และนำไปใช้


เมื่อพิจารณาความสัมพันธ์ข้ามของเวกเตอร์สัญญาณสุ่มสองตัว คุณจะใช้การย้อนกลับเพื่อให้ได้เวกเตอร์สองตัวใน MATLAB ได้อย่างไร John Muhehe

คำตอบ:


56

ความสัมพันธ์ข้ามและการโน้มน้าวมีความสัมพันธ์กันอย่างใกล้ชิด ในระยะสั้นเพื่อทำสังวัตนากับ FFT คุณ

  1. zero-pad สัญญาณอินพุต (เพิ่มศูนย์ไปยังจุดสิ้นสุดเพื่อให้อย่างน้อยครึ่งหนึ่งของคลื่นเป็น "ช่องว่าง")
  2. ใช้ FFT ของสัญญาณทั้งสอง
  3. คูณผลลัพธ์เข้าด้วยกัน (การคูณองค์ประกอบที่ชาญฉลาด)
  4. ทำ FFT ผกผัน

conv(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros))

คุณต้องทำการ zero-padding เนื่องจากวิธีการ FFT เป็นความสัมพันธ์ข้ามแบบวงกลมซึ่งหมายความว่าสัญญาณถูกล้อมรอบที่ปลาย ดังนั้นคุณจึงเพิ่มศูนย์พอที่จะกำจัดการทับซ้อนเพื่อจำลองสัญญาณที่ไม่มีศูนย์

ในการรับcross-correlationแทนที่จะเป็น convolution คุณต้องย้อนกลับสัญญาณใดสัญญาณหนึ่งก่อนที่จะทำ FFT หรือใช้การรวมกันที่ซับซ้อนของสัญญาณใดสัญญาณหนึ่งหลังจาก FFT:

  • corr(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros[reversed]))
  • corr(a, b) = ifft(fft(a_and_zeros) * conj(fft(b_and_zeros)))

ไม่ว่าฮาร์ดแวร์หรือซอฟต์แวร์ของคุณจะเป็นอะไรก็ตาม สำหรับ autocorrelation (cross-correlation ของสัญญาณด้วยตัวมันเอง) มันจะเป็นการดีกว่าถ้าคุณทำการผันคำกริยาที่ซับซ้อนเพราะคุณจะต้องคำนวณ FFT เพียงครั้งเดียว

หากสัญญาณเป็นจริงคุณสามารถใช้ FFT จริง (RFFT / IRFFT) และประหยัดเวลาการคำนวณครึ่งหนึ่งของคุณโดยการคำนวณเพียงครึ่งหนึ่งของสเปกตรัม

นอกจากนี้คุณสามารถประหยัดเวลาในการคำนวณได้ด้วยการขยายขนาดให้ใหญ่ขึ้นซึ่ง FFT นั้นได้รับการปรับให้เหมาะสมที่สุด (เช่นหมายเลข5-smoothสำหรับ FFTPACK, หมายเลข~ 13-smooth สำหรับ FFTWหรือกำลังของ 2 สำหรับการใช้ฮาร์ดแวร์อย่างง่าย)

นี่คือตัวอย่างใน Python ที่มีความสัมพันธ์แบบ FFT เทียบกับความสัมพันธ์แบบ brute-force: https://stackoverflow.com/a/1768140/125507

สิ่งนี้จะทำให้คุณมีฟังก์ชันข้ามสหสัมพันธ์ซึ่งเป็นการวัดความคล้ายคลึงกันเทียบกับออฟเซ็ต เพื่อให้ได้ค่าออฟเซตที่คลื่น "เรียงกัน" กันจะมีจุดสูงสุดในฟังก์ชันสหสัมพันธ์:

จุดสูงสุดในฟังก์ชันสหสัมพันธ์

ค่า x ของจุดสูงสุดคือ offset ซึ่งอาจเป็นลบหรือบวก

ฉันเพิ่งเห็นสิ่งนี้เคยพบการชดเชยระหว่างสองคลื่น คุณสามารถรับค่าประมาณของการชดเชยที่แม่นยำยิ่งขึ้น (ดีกว่าความละเอียดของตัวอย่างของคุณ) โดยใช้การประมาณพาราโบลา / กำลังสองบนจุดสูงสุด

ในการรับค่าความคล้ายคลึงกันระหว่าง -1 และ 1 (ค่าลบที่ระบุว่าสัญญาณใดสัญญาณหนึ่งลดลงตามการเพิ่มขึ้นอื่น ๆ ) คุณจะต้องปรับขนาดแอมพลิจูดตามความยาวของอินพุตความยาวของ FFT การใช้ FFT เฉพาะของคุณ การปรับขนาด ฯลฯ ความสัมพันธ์อัตโนมัติของคลื่นด้วยตัวเองจะให้คุณค่าของการจับคู่ที่เป็นไปได้สูงสุด

โปรดทราบว่าจะใช้งานได้กับคลื่นที่มีรูปร่างเหมือนกัน หากพวกเขาถูกสุ่มตัวอย่างบนฮาร์ดแวร์ที่แตกต่างกันหรือมีสัญญาณรบกวนบางส่วน แต่อย่างอื่นยังคงมีรูปร่างเดียวกันการเปรียบเทียบนี้จะใช้งานได้ แต่ถ้ารูปร่างคลื่นมีการเปลี่ยนแปลงโดยการกรองหรือการเปลี่ยนเฟสพวกเขาอาจฟังดูเหมือนกัน แต่ชนะ ไม่สัมพันธ์เช่นกัน


3
การเติมเต็มศูนย์ควรมีอย่างน้อย N = ขนาด (a) + ขนาด (b) -1 โดยเฉพาะควรปัดขึ้นให้มีกำลังเป็น 2 เพื่อให้ได้ค่าระหว่าง -1 ถึง 1 ให้หารด้วย norm (a) * norm (b) ) ซึ่งให้มุมของโคไซน์ระหว่างสองเวกเตอร์ใน N-space สำหรับความล่าช้าที่ระบุ ที่ความล่าช้ามากมีตัวอย่างที่ซ้อนทับกันไม่มาก (เพียงหนึ่งที่ไกลสุด) ดังนั้นการหารด้วย norm (a) * norm (b) จะมีอคติสหสัมพันธ์เหล่านี้ต่อ 0 (เช่นแสดงความสัมพันธ์ของพวกเขาใน N-space) .
Eryk Sun

1
ฉันคิดว่าอาจมีข้อผิดพลาดในคำอธิบาย ไม่ควรคูณ FFT เข้าด้วยกันเป็นระยะโดยการกำหนดให้ FFT ของการโน้มน้าวใจของสัญญาณไม่ใช่ FFT ของความสัมพันธ์ข้าม ? ตามที่ฉันเข้าใจเพื่อให้ได้ค่า FFT ของค่าสหสัมพันธ์ (cross-correlation) มีความจำเป็นต้องใช้คอนจูเกตที่ซับซ้อนของเวกเตอร์ FFT ตัวใดตัวหนึ่งในการคูณแบบคำต่อคำก่อนทำการ iFFT
Dilip Sarwate

@DilipSarwate: ใช่คุณพูดถูก คุณยังสามารถสลับสัญญาณหนึ่งสัญญาณในทิศทางเวลาซึ่งฉันเพิ่มไปยังคำตอบ
endolith

1
"ทำไมเวลากลับยากที่จะทำในฮาร์ดแวร์" ในหลายกรณีข้อมูลจะถูกเก็บไว้ในอาร์เรย์ systolic ในการคาดการณ์ว่าการคำนวณที่มีในท้องถิ่นเช่น , เก็บไว้ในเซลล์ -th ปฏิสัมพันธ์เฉพาะกับประเทศเพื่อนบ้านที่ใกล้ที่สุดนผม] ส่งไปยังเซลล์ #และการส่งไปยังเซลล์ #และทำเช่นนี้สำหรับทุกคนเพิ่มค่าใช้จ่ายสายไฟ, ความล่าช้าในการเดินสายไฟ (และด้วยเหตุนี้จะช่วยลดอัตรานาฬิกาสูงสุดทำได้) และยังเพราะทั้งหมด สายไฟจะต้องข้ามกันสร้างปัญหาการกำหนดเส้นทาง ควรหลีกเลี่ยงหากเป็นไปได้และในกรณีนี้สามารถหลีกเลี่ยงได้ฉันxx[i]ix [ i ] ( N - i ) x [ N - i ] i ix[±i]x[i](Ni)x[Ni]ii
Dilip Sarwate

1
@ คูณคูณองค์ประกอบที่ชาญฉลาด n-by-1 array x n-by-1 array = n-by-1 array ฉันเรียกสิ่งนี้ว่า "sample-by-sample" ในคำตอบ
endolith

17

ความสัมพันธ์เป็นวิธีที่แสดงความคล้ายคลึงกันของสองชุดเวลา (ตัวอย่างเสียงในกรณีของคุณ) ในหนึ่งหมายเลข มันเป็นการปรับตัวของความแปรปรวนร่วมซึ่งมีการดำเนินการดังต่อไปนี้:

period = 1/sampleFrequency;
covariance=0;

for (iSample = 0; iSample<nSamples; iSample++)
    covariance += (timeSeries_1(iSample)*timeSeries_2(iSample))/period;
    //Dividing by `period` might not even be necessary

ความสัมพันธ์คือความแปรปรวนร่วมแบบปกติซึ่งเป็นความแปรปรวนร่วมหารด้วยผลคูณของส่วนเบี่ยงเบนมาตรฐานของอนุกรมเวลาทั้งคู่ ความสัมพันธ์จะให้ผลเป็น 0 เมื่อไม่มีความสัมพันธ์ (ไม่เหมือนกันทั้งหมด) และ 1 สำหรับความสัมพันธ์ทั้งหมด (คล้ายกันทั้งหมด)

คุณสามารถจินตนาการได้ว่าตัวอย่างเสียงสองตัวอย่างอาจคล้ายกัน แต่ไม่ได้ซิงโครไนซ์ นั่นคือสิ่งที่มีความสัมพันธ์ไขว้เข้ามาคุณคำนวณความสัมพันธ์ระหว่างอนุกรมเวลาที่คุณมีหนึ่งในนั้นเปลี่ยนโดยตัวอย่างหนึ่ง:

for (iShift=0; iShift<nSamples; iShift++)
    xcorr(iShift) = corr(timeSeries_1, timeSeries_2_shifted_one_sample);

จากนั้นหาค่าสูงสุดในcorrซีรีส์และคุณทำเสร็จแล้ว (หรือหยุดถ้าคุณพบความสัมพันธ์ที่เพียงพอ) แน่นอนว่ามีมากกว่านั้น คุณต้องใช้ค่าเบี่ยงเบนมาตรฐานและคุณต้องทำการจัดการหน่วยความจำและนำสิ่งที่เปลี่ยนเวลา หากตัวอย่างเสียงทั้งหมดของคุณมีความยาวเท่ากันคุณอาจทำได้โดยไม่ทำให้ค่าความแปรปรวนร่วมเป็นปกติและไปข้างหน้าและคำนวณค่าความแปรปรวนร่วมแบบข้าม

ความสัมพันธ์ที่ดีกับคำถามก่อนหน้าของคุณ : การวิเคราะห์ฟูริเยร์เป็นเพียงการปรับตัวของความแปรปรวนร่วมแบบครอส แทนที่จะทำการเปลี่ยนอนุกรมหนึ่งครั้งและคำนวณโควาเรียสกับสัญญาณอื่นคุณคำนวณโควาเรียสระหว่างสัญญาณหนึ่งกับคลื่นไซน์จำนวนหนึ่ง (co) ที่มีความถี่ต่างกัน ทุกอย่างขึ้นอยู่กับหลักการเดียวกัน


1
คุณพูดถึงว่า 0 ไม่มีความสัมพันธ์และ 1 คือความสัมพันธ์ทั้งหมด ฉันแค่ต้องการทราบว่า -1 นั้นมีความสัมพันธ์เชิงลบอย่างสมบูรณ์ ดังเช่นใน -1 หมายถึงตัวอย่างที่ 1 นั้นตรงข้ามกับตัวอย่างที่ 2 ถ้าคุณคิดถึงมันในกราฟ X, Y มันเป็นเส้นที่มีความชันเป็นบวกเมื่อเทียบกับเส้นที่มีความชันเป็นลบ และเมื่อคุณเข้าใกล้ 0 มากขึ้นบรรทัดจะได้รับ "อ้วนขึ้น"
Kellenjb

@ kellenjb ใช่ แต่ฉันอาจจะบอกว่าขนาดของความสัมพันธ์ที่คุณอาจสนใจ 1 หรือ -1 หมายถึงสัญญาณที่ส่งผลกระทบโดยตรงต่อกัน
Kortuk

13

ในการประมวลผลสัญญาณ cross-correlation (xcorr ใน MATLAB) เป็นการดำเนินการสังวัตนาโดยที่หนึ่งในสองลำดับย้อนกลับ เนื่องจากการกลับเวลาสอดคล้องกับการผันคำกริยาที่ซับซ้อนในโดเมนความถี่คุณสามารถใช้ DFT เพื่อคำนวณความสัมพันธ์ข้ามได้ดังนี้

R_xy = ifft(fft(x,N) * conj(fft(y,N)))

โดยที่ N = size (x) + size (y) - 1 (โดยเฉพาะการปัดเศษขึ้นให้มีกำลังมาก 2) คือความยาวของ DFT

การทวีคูณของ DFT นั้นเทียบเท่ากับการวนเป็นวงกลมในเวลา การซ้อนศูนย์ทั้งเวกเตอร์จนถึงความยาว N ทำให้องค์ประกอบที่เลื่อนแบบวงกลมของ y ไม่ทับซ้อนกับ x ซึ่งทำให้ผลลัพธ์เหมือนกับการแปลงเชิงเส้นของ x และเวลาที่กลับด้าน y

ความล่าช้าของ 1 คือการเลื่อนแบบวงกลมด้านขวาของ y ในขณะที่ความล่าช้าของ -1 เป็นการเลื่อนแบบวงกลมซ้าย cross-correlation เป็นเพียงลำดับของจุดสำหรับความล่าช้าทั้งหมด ตามลำดับการ fft มาตรฐานเหล่านี้จะอยู่ในอาร์เรย์ที่สามารถเข้าถึงได้ดังต่อไปนี้ ดัชนี 0 ถึงขนาด (x) -1 คือความล่าช้าในเชิงบวก ดัชนี N-size (y) +1 ถึง N-1 เป็นค่าลบติดลบในลำดับย้อนกลับ (ใน Python คุณสามารถเข้าถึงความล่าช้าเชิงลบได้อย่างสะดวกด้วยดัชนีลบเช่น R_xy [-1])

คุณสามารถคิดถึง x และ y ที่เป็นศูนย์และ y เป็นเวกเตอร์มิติ N ผลิตภัณฑ์ที่จุดของ x และ y |x|*|y|*cos(theta)สำหรับความล่าช้าที่ได้รับคือ บรรทัดฐานของ x และ y เป็นค่าคงที่สำหรับการเลื่อนแบบวงกลมดังนั้นการหารพวกมันออกจากใบไม้แค่โคไซน์ที่ต่างกันของมุมทีต้า ถ้า x และ y (สำหรับความล่าช้าที่กำหนด) เป็นมุมฉากใน N-space ความสัมพันธ์คือ 0 (เช่น theta = 90 องศา) หากพวกมันเป็นแบบเชิงเส้นร่วมค่าจะเป็น 1 (มีความสัมพันธ์เชิงบวก) หรือ -1 (มีความสัมพันธ์เชิงลบนั่นคือ theta = 180 องศา) สิ่งนี้นำไปสู่การข้ามสหสัมพันธ์ที่ทำให้เป็นเอกภาพ:

R_xy = ifft(fft(x,N) * conj(fft(y,N))) / (norm(x) * norm(y))

สิ่งนี้สามารถทำให้เป็นกลางโดยการคำนวณบรรทัดฐานใหม่สำหรับส่วนที่ทับซ้อนกัน แต่จากนั้นคุณอาจทำการคำนวณทั้งหมดในโดเมนเวลา นอกจากนี้คุณจะเห็นเวอร์ชันการปรับมาตรฐานที่แตกต่างกัน แทนที่จะเป็นมาตรฐานสู่ความเป็นเอกภาพบางครั้งความสัมพันธ์ข้ามถูกทำให้เป็นมาตรฐานโดย M (เอนเอียง) โดยที่ M = สูงสุด (ขนาด (x), ขนาด (y)), หรือ M- | m | (การประมาณที่ไม่เอนเอียงของ mth lag)

สำหรับนัยสำคัญทางสถิติสูงสุดควรหาค่าเฉลี่ย (DC bias) ก่อนคำนวณความสัมพันธ์ สิ่งนี้เรียกว่า cross-covariance (xcov in MATLAB):

x2 = x - mean(x)
y2 = y - mean(y)
phi_xy = ifft(fft(x2,N) * conj(fft(y2,N))) / (norm(x2) * norm(y2))

นี่หมายความว่าขนาดสุดท้ายของอาร์เรย์ควรเป็น2*size (a) + size(b) - 1หรือ2*size (b) + size (a) - 1? แต่ในทั้งสองกรณีเบาะรองสองแถวมีขนาดแตกต่างกัน ผลที่ตามมาของการเติมด้วยศูนย์มีมากเกินไปคืออะไร

@RobertK อาเรย์ข้ามความสัมพันธ์ต้องมีความยาวอย่างน้อยผลรวมของความยาวของ a และ b (ลบหนึ่ง) ตามที่ eryksun กล่าวในคำตอบของเขา สำหรับความเรียบง่ายความยาวมักถูกนำมาเป็นสองเท่าของความยาวของเวกเตอร์ที่ยาวขึ้น (บางครั้งก็ปัดขึ้นเป็นกำลังที่ใหญ่กว่าถัดไปเป็นเพื่อใช้ FFT ที่มีประสิทธิภาพ) ตัวเลือกช่วยเมื่อลูกค้าตัดสินใจอย่างล่าช้าเขาต้องการความสัมพันธ์ของเวกเตอร์ที่ยาวกว่า ผลลัพธ์อย่างหนึ่งของการขยายที่มีเลขศูนย์มากเกินไปคือการคำนวณเพิ่มเติม แต่สิ่งนี้อาจได้รับการแก้ไขด้วยการใช้ FFT ที่มีประสิทธิภาพมากขึ้น 2
Dilip Sarwate

@RobertKJ: คุณเลื่อนbไปพร้อมaกับหนึ่งเอาต์พุตต่อการเปลี่ยนแปลงการทับซ้อนขั้นต่ำของหนึ่งตัวอย่าง ที่ให้ผลsize(a)บวกและsize(b) - 1ล่าช้าเชิงลบ การใช้การแปลงผกผันของผลิตภัณฑ์ของ N-point DFTs ดัชนี0ผ่านsize(a)-1คือความล่าช้าในเชิงบวกและดัชนีN-size(b)+1ผ่านN-1เป็นความล่าช้าเชิงลบในลำดับย้อนกลับ
Eryk Sun

3

ถ้าคุณใช้ Matlab ลองใช้ฟังก์ชั่น cross correlate:

c= xcorr(x,y)

นี่คือเอกสารประกอบ Matlab:

xcorrประเมินลำดับความสัมพันธ์ข้ามของกระบวนการสุ่ม Autocorrelation ถูกจัดการเป็นกรณีพิเศษ

...

c = xcorr(x,y)ส่งคืนลำดับความสัมพันธ์ข้ามในความยาว 2 * N-1 เวกเตอร์โดยที่xและyเป็นNเวกเตอร์ความยาว( N > 1) ถ้าxและyไม่ใช่ความยาวเดียวกันเวกเตอร์ที่สั้นกว่านั้นจะเป็นศูนย์ซึ่งเท่ากับความยาวของเวกเตอร์ที่ยาวกว่า

correlation http://www.mathworks.com/help/toolbox/signal/ref/eqn1263487323.gif


ดูเหมือนว่าลิงก์จะใช้งานไม่ได้
Danijel

2

วิธีที่รวดเร็วและง่ายในการเปรียบเทียบไฟล์เสียง นำไฟล์เสียงทำสำเนาวางบนด้านข้างในช่องสเตอริโอ 2 ช่องกลับด้านในแทร็กสเตอริโอหนึ่งช่องจัดแนวไฟล์ทั้งสองที่จุดเริ่มต้นในโหมดซูมตรวจสอบให้แน่ใจว่า ไฟล์ทั้งสองมีแอมพลิจูดเหมือนกันในตอนเริ่มต้นจากนั้นเล่นถ้ามีความเงียบโดยรวมไฟล์ทั้งสองจะเหมือนกันหากมีความแตกต่างคุณจะได้ยินชัดเจนมาก!


1

ส่วนใหญ่ที่นี่เขียนคุณควรใช้ความสัมพันธ์

เพียงพิจารณาปัจจัย 2 ประการ:

  1. หากปรับระดับเสียงให้แตกต่างกันคุณควรทำให้ค่าสหสัมพันธ์เป็นปกติ
  2. หากมีการปรับขนาดของเวลาจากนั้นคุณอาจใช้การแปรปรวนเวลาแบบไดนามิก

0

วิธีที่ง่ายที่สุดในการค้นหาความแตกต่างคือ IMO คือการลบสัญญาณเสียงสองสัญญาณในโดเมนเวลา หากพวกเขาเท่ากันผลลัพธ์ที่จุดทุกเวลาจะเป็นศูนย์ หากพวกเขาไม่เท่ากันความแตกต่างระหว่างพวกเขาจะถูกทิ้งไว้หลังจากการลบและคุณสามารถฟังได้โดยตรง การวัดอย่างรวดเร็วว่ามีความคล้ายคลึงกันมากน้อยเพียงใดคือค่า RMS ของความแตกต่างนี้ มักจะทำในการผสมเสียงและควบคุมเพื่อฟังความแตกต่างของไฟล์ MP3 vs WAV เช่น (อินเวอร์เตอร์เฟสของสัญญาณเดียวและการเพิ่มพวกมันก็เหมือนกับการลบนี่เป็นวิธีที่ใช้เมื่อทำในซอฟต์แวร์ DAW) พวกมันจะต้องจัดเวลาให้สมบูรณ์เพื่อให้ทำงานได้ หากไม่ใช่คุณสามารถพัฒนาอัลกอริทึมเพื่อจัดแนวพวกเขาเช่นการตรวจหายอดเขาสิบอันดับแรกการคำนวณออฟเซ็ตเฉลี่ยของยอดเขาและเปลี่ยนสัญญาณหนึ่งสัญญาณ

การแปลงเป็นโดเมนความถี่และเปรียบเทียบสเปกตรัมพลังงานของสัญญาณเช่นเดียวกับที่คุณเสนอจะไม่สนใจข้อมูลโดเมนเวลา ตัวอย่างเช่นเสียงที่เล่นในสิ่งที่ตรงกันข้ามจะมีคลื่นความถี่เดียวกันเมื่อเล่นไปข้างหน้า ดังนั้นสัญญาณเสียงที่แตกต่างกันสองอย่างอาจมีคลื่นความถี่เดียวกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.