Trong một trang trình bày trong bài giảng giới thiệu về máy học của Andrew Ng tại Coursera, Stanford, ông đưa ra giải pháp Octave một dòng sau đây cho vấn đề tiệc cocktail với điều kiện các nguồn âm thanh được ghi lại bằng hai micrô được phân tách theo không gian:
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
Ở cuối trang trình bày là "nguồn: Sam Roweis, Yair Weiss, Eero Simoncelli" và ở cuối trang trình bày trước đó là "Đoạn âm thanh lịch sự của Te-Won Lee". Trong video, Giáo sư Ng nói,
"Vì vậy, bạn có thể nhìn vào việc học không giám sát như thế này và hỏi, 'Làm thế nào phức tạp để thực hiện điều này?' Có vẻ như để xây dựng ứng dụng này, có vẻ như để xử lý âm thanh này, bạn sẽ viết rất nhiều mã hoặc có thể liên kết vào một loạt các thư viện C ++ hoặc Java để xử lý âm thanh. Có vẻ như nó sẽ là một chương trình phức tạp để thực hiện âm thanh này: tách ra âm thanh, v.v. Hóa ra thuật toán để thực hiện những gì bạn vừa nghe, điều đó có thể được thực hiện chỉ với một dòng mã ... được hiển thị ngay tại đây. Các nhà nghiên cứu đã mất nhiều thời gian để đưa ra dòng mã này. Vì vậy, tôi không nói đây là một vấn đề dễ dàng. Nhưng hóa ra là khi bạn sử dụng môi trường lập trình phù hợp, nhiều thuật toán học sẽ là những chương trình thực sự ngắn. "
Kết quả âm thanh tách biệt được phát trong video bài giảng không hoàn hảo nhưng theo tôi, thật tuyệt vời. Có ai có bất kỳ thông tin chi tiết nào về cách một dòng mã hoạt động tốt như vậy không? Đặc biệt, có ai biết tài liệu tham khảo giải thích công việc của Te-Won Lee, Sam Roweis, Yair Weiss và Eero Simoncelli liên quan đến một dòng mã đó không?
CẬP NHẬT
Để chứng minh độ nhạy của thuật toán đối với khoảng cách tách micrô, mô phỏng sau đây (trong Octave) tách các âm từ hai bộ tạo âm cách nhau theo không gian.
% define model
f1 = 1100; % frequency of tone generator 1; unit: Hz
f2 = 2900; % frequency of tone generator 2; unit: Hz
Ts = 1/(40*max(f1,f2)); % sampling period; unit: s
dMic = 1; % distance between microphones centered about origin; unit: m
dSrc = 10; % distance between tone generators centered about origin; unit: m
c = 340.29; % speed of sound; unit: m / s
% generate tones
figure(1);
t = [0:Ts:0.025];
tone1 = sin(2*pi*f1*t);
tone2 = sin(2*pi*f2*t);
plot(t,tone1);
hold on;
plot(t,tone2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('tone 1', 'tone 2');
hold off;
% mix tones at microphones
% assume inverse square attenuation of sound intensity (i.e., inverse linear attenuation of sound amplitude)
figure(2);
dNear = (dSrc - dMic)/2;
dFar = (dSrc + dMic)/2;
mic1 = 1/dNear*sin(2*pi*f1*(t-dNear/c)) + \
1/dFar*sin(2*pi*f2*(t-dFar/c));
mic2 = 1/dNear*sin(2*pi*f2*(t-dNear/c)) + \
1/dFar*sin(2*pi*f1*(t-dFar/c));
plot(t,mic1);
hold on;
plot(t,mic2,'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -1 1]); legend('mic 1', 'mic 2');
hold off;
% use svd to isolate sound sources
figure(3);
x = [mic1' mic2'];
[W,s,v]=svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x');
plot(t,v(:,1));
hold on;
maxAmp = max(v(:,1));
plot(t,v(:,2),'r'); xlabel('time'); ylabel('amplitude'); axis([0 0.005 -maxAmp maxAmp]); legend('isolated tone 1', 'isolated tone 2');
hold off;
Sau khoảng 10 phút thực hiện trên máy tính xách tay của tôi, mô phỏng tạo ra ba hình sau minh họa hai âm riêng biệt có tần số chính xác.
Tuy nhiên, việc đặt khoảng cách tách micrô thành 0 (tức là dMic = 0) khiến mô phỏng thay vào đó tạo ra ba hình sau minh họa mô phỏng không thể tách âm thứ hai (được xác nhận bởi số hạng đường chéo quan trọng duy nhất được trả về trong ma trận svd).
Tôi đã hy vọng khoảng cách tách micrô trên điện thoại thông minh sẽ đủ lớn để tạo ra kết quả tốt nhưng việc đặt khoảng cách tách micrô thành 5,25 inch (tức là dMic = 0,1333 mét) khiến mô phỏng tạo ra những điều sau đây, ít hơn đáng khích lệ, các số liệu minh họa cao hơn các thành phần tần số trong âm cách biệt đầu tiên.
x
được là gì ; nó là quang phổ của dạng sóng, hay là gì?