วันเสาร์ที่ 4 มิถุนายน พ.ศ. 2565

การทำให้ 2 เสียงที่เหมือนกันไม่เกิดการ Delay

สวัสดีครับ แอดได้ไปลองแกะโคดแล้วเจอวิธีที่ทำให้เสียง 2 เสียงที่เหมือนกัน แต่บางครั้งเกิดการ Delay ได้ดังรูป



Sound1



Sound2



จะเห็นว่า คลื่นเสียงที่ 1 และ คลื่นเสียงที่ 2 มีรูปคลื่นเหมือนกันเลย ยกเว้นช่วงเวลาที่ต่างกัน ก็คือ เสียงเพลงที่ 1 จะเริ่มเล่นก่อน แล้วเสียงเพลงที่ 2 ค่อยเริ่มเล่นตาม


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





"แล้วเราจะรู้ได้อย่างไรว่าควรตัดช่วงเริ่มต้นของเพลงออกกี่วินาที ถึงจะทำให้เล่นเพลงที่ 1 กับ 2 พร้อมกันได้"

ถ้าในการเขียนโคดวิธีนึงนั้นเราจะใช้การคำนวณ correlate เข้ามาช่วย




จากวีดีโอด้านบน การคำนวณ Correlate จะเป็นการคำนวณโดยการเอาเสียงที่ต้องการเปรียบเทียบมาทาบในแต่ละช่วงเวลาแล้วคำนวณค่า Correlate ซึ่งช่วงเวลาใหนมีค่า Correlate มากที่สุดแสดงว่าช่วงเวลานั้นมีความใกล้เคียงกับเสียงที่เปรียบเทียบมากที่สุดนั่นเอง

เมื่อเราได้ช่วงเวลาที่ให้ค่า Correlate ที่มากที่สุด เราก็สามารถตัดช่วงเวลาก่อนหน้าออกได้เลยนั่นเอง



จากที่กล่าวมาทั้งหมดคือการทำ Correlate แบบคร่าวๆให้เข้าใจได้ง่ายและเห็นภาพ ต่อมาเราจะมาเขียนโคดกัน

แต่ก่อนจะเขียนโคด ขออธิบายหน้าตาข้อมูลที่ใช้ในการเก็บเสียงเพลงกันก่อนครับ

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


Sound1





Sound2

เมื่อเราได้ข้อมูลของเสียงมาแล้ว เราก็จะเขียนโคดได้ดังนี้

offset = len(sound1) - 1
delay = np.argmax(np.correlate(sound1, sound2, 'full')) - offset

if delay > 0:
    sound1 = sound1[:, delay:]
else:
    sound2 = sound2[:, np.abs(delay):]


จากโคดจะเห็นว่าเรามีคำสั่ง np.correlate(sound1, sound2, 'full') หรือก็คือการนำ Sound1 กับ Sound2 มา correlate กันดังวีดีโอด้านล่าง





หลังจาก correlate กันแล้วเราก็จะเลือกช่วงที่มีคะแนนที่มากที่สุดโดยใช้คำสั่ง np.armax(...) โดย np.armax(...) จะให้ตำแหน่งที่มากที่สุดมานั่นเอง

หลังจากนั้นเราก็เอาตำแหน่งที่ได้มาลบกับ ช่วงทั้งหมดของเสียง Sound1 ก็คือการนำมาลบกับ offset

delay = np.argmax(np.correlate(sound1, sound2, 'full')) - offset


เมื่อทำการลบ แล้วก็ได้ช่วงที่ Delay มา หลังจากนั้นเราก็สามารถ เอาช่วงที่เริ่มต้นที่เหลือมออกโดยใช้โคดด้านล่างครับ

if delay > 0:
    a = a[:, delay:]
else:
    b = b[:, np.abs(delay):]



"แล้วการคำนวณ Correlate คำนวณอย่างไร"

ในการคำนวณ Correlate ในคลื่นเสียงนั้นจะเอาเสียงมาทาบ แล้วหาผลบวกของผลคูณของตำแหน่งที่ตรงกัน เพื่อให้เข้าใจมากขึ้นมาดูตัวอย่างกันครับ

ตัวอย่างที่ 1

ในการทาบช่วงเวลาดังกล่าวก็จะได้ค่า Correlate เป็น 0.02 คือการคำนวณจาก 

(0.1 x 0.2) = 0.02



ตัวอย่างที่ 2


ในการทาบช่วงเวลาดังกล่าวก็จะได้ค่า Correlate เป็น 0.19 คือการคำนวณจาก 


(0.1 x -0.1) + (1 x 0.2) = 0.19



ตัวอย่างที่ 3

ในการทาบช่วงเวลาดังกล่าวก็จะได้ค่า Correlate เป็น 0.19 คือการคำนวณจาก 


(0.1 x 1) + (1 x -0.1) + (-1 x 0.2) = -0.2


สุดท้ายนี้หวังว่าโพสน์นี้จะมีประโยชน์นะครับ 😁 ขอบคุณครับ