W ramach projektu zabawy w domu, próbuję znaleźć sposób na zredukowanie/przekonwertowanie piosenki do buczenia jak sygnał audio (podstawowa melodia, którą my, ludzie, postrzegamy, gdy słuchamy piosenki). Zanim przejdę dalej opisując moją próbę rozwiązania tego problemu, chciałbym wspomnieć, że jestem całkowicie nowy w analizie dźwięku, chociaż mam duże doświadczenie w analizowaniu obrazów i filmów.Jak przekonwertować ścieżkę tonacji z algorytmu wyodrębniania melodii na brzęczenie jak sygnał dźwiękowy?
Po trochę google, znalazłem kilka algorytmów ekstrakcji melodii. Biorąc pod uwagę polifoniczny sygnał dźwiękowy utworu (np. Plik .wav), wyprowadzają ścieżkę tonacji - w każdym momencie oceniają dominującą tonację (pochodzącą od głosu wokalisty lub jakiegoś instrumentu generującego melodię) i śledzą dominującą nachylenie w czasie.
Przeczytałem kilka artykułów i zdają się obliczać transformatę Fouriera utworu, a następnie przeprowadzić analizę spektrogramu, aby uzyskać i śledzić dominujący ton. Wyodrębnianie melodii jest tylko częścią systemu, który próbuję rozwijać, więc nie mam nic przeciwko używaniu jakiegokolwiek algorytmu, który jest dostępny, o ile wykonuje przyzwoite zadanie na moich plikach audio i kod jest dostępny. Ponieważ jestem na tym początku, chętnie usłyszę wszelkie sugestie na temat tego, które algorytmy działają dobrze i gdzie mogę znaleźć jego kod.
znalazłem dwa algorytmy:
Wybrałem Melodia jak wyniki na różnych gatunkach muzycznych wyglądał całkiem imponujące. Proszę sprawdzić this to see its results. Brzęczenie, które słyszysz dla każdego utworu jest w istocie tym, co mnie interesuje.
"To pokolenie tego nucenia dla jakiejkolwiek arbitralnej piosenki, z którą chcę ci pomóc w tym pytaniu".
Algorytm (dostępny jako wtyczka dla wampirów) wyświetla ścieżkę tonacji --- [time_stamp, wysokość/częstotliwość] --- macierz Nx2, w której w pierwszej kolumnie znajduje się znacznik czasu (w sekundach) i sekunda kolumna jest wykrywana dominującym tonem w odpowiednim znaczniku czasu. Poniżej pokazano wizualizację ścieżki dźwiękowej uzyskanej z algorytmu nałożonego na fioletowy kolor z sygnałem w dziedzinie czasu piosenki (powyżej) i spektrogramu/krótkiego czasu-czwartego. Wartości ujemne skoku/częstotliwości reprezentują algorytmy oceny dominującego skoku dla segmentów nie-dźwięcznych/nie-melodycznych. Więc wszystkie oceny pochylenia> = 0 odpowiadają melodii, reszta nie jest dla mnie ważna.
Teraz chcę przekonwertować ten odstęp ścieżek z powrotem do brzęczenia jak sygnału audio - podobnie jak autorzy mają go na swojej stronie internetowej.
Poniżej znajduje się funkcja MATLAB, że napisałem to zrobić:
function [melSignal] = melody2audio(melody, varargin)
% melSignal = melody2audio(melody, Fs, synthtype)
% melSignal = melody2audio(melody, Fs)
% melSignal = melody2audio(melody)
%
% Convert melody/pitch-track to a time-domain signal
%
% Inputs:
%
% melody - [time-stamp, dominant-frequency]
% an Nx2 matrix with time-stamp in the
% first column and the detected dominant
% frequency at corresponding time-stamp
% in the second column.
%
% synthtype - string to choose synthesis method
% passed to synth function in synth.m
% current choices are: 'fm', 'sine' or 'saw'
% default='fm'
%
% Fs - sampling frequency in Hz
% default = 44.1e3
%
% Output:
%
% melSignal -- time-domain representation of the
% melody. When you play this, you
% are supposed to hear a humming
% of the input melody/pitch-track
%
p = inputParser;
p.addRequired('melody', @isnumeric);
p.addParamValue('Fs', 44100, @(x) isnumeric(x) && isscalar(x));
p.addParamValue('synthtype', 'fm', @(x) ismember(x, {'fm', 'sine', 'saw'}));
p.addParamValue('amp', 60/127, @(x) isnumeric(x) && isscalar(x));
p.parse(melody, varargin{:});
parameters = p.Results;
% get parameter values
Fs = parameters.Fs;
synthtype = parameters.synthtype;
amp = parameters.amp;
% generate melody
numTimePoints = size(melody,1);
endtime = melody(end,1);
melSignal = zeros(1, ceil(endtime*Fs));
h = waitbar(0, 'Generating Melody Audio');
for i = 1:numTimePoints
% frequency
freq = max(0, melody(i,2));
% duration
if i > 1
n1 = floor(melody(i-1,1)*Fs)+1;
dur = melody(i,1) - melody(i-1,1);
else
n1 = 1;
dur = melody(i,1);
end
% synthesize/generate signal of given freq
sig = synth(freq, dur, amp, Fs, synthtype);
N = length(sig);
% augment note to whole signal
melSignal(n1:n1+N-1) = melSignal(n1:n1+N-1) + reshape(sig,1,[]);
% update status
waitbar(i/size(melody,1));
end
close(h);
end
Podstawowym logika tego kodu jest następujący: w każdym czasie znaczek, ja syntezy falę krótkotrwały (słownie sine -fala) z częstotliwością równą wykrytej dominującej częstotliwości/częstotliwości w tym znaczniku czasu przez czas równy jej luce z następnym znacznikiem czasu w macierzy melodii wejściowych. Zastanawiam się tylko, czy robię to dobrze.
Następnie biorę sygnał dźwiękowy, który otrzymuję z tej funkcji i odtwarzam z oryginalnym utworem (melodia na lewym kanale i oryginalna piosenka na prawym kanale).Chociaż wygenerowany sygnał dźwiękowy wydaje się dość dobrze segmentować źródła generujące melodię (głos/ołów-instrument) - jego aktywny głos jest wszędzie i zero wszędzie - sam sygnał daleki jest od brzęczenia (dostaję coś w stylu Beep Beep Beeeeep Beep Beep Beeeeeeeep), które autorzy pokazują na swojej stronie internetowej. Poniżej znajduje się wizualizacja pokazująca sygnał w dziedzinie czasu wejściowej piosenki na dole i sygnał w domenie czasu melodii wygenerowanej za pomocą mojej funkcji.
Jeden główny problem jest - chociaż ja biorąc pod uwagę częstotliwość fali do generowania w każdym czasie znaczek, a także czas trwania, nie wiem jak ustawić amplitudę fali. Na razie ustawiłem amplitudę na płaską/a-stałą wartość i podejrzewam, że to jest problem.
Czy ktoś ma jakieś sugestie na ten temat? Z zadowoleniem przyjmuję sugestie w dowolnym języku programowania (najlepiej MATLAB, python, C++), ale myślę, że moje pytanie tutaj jest bardziej ogólne --- Jak generować falę przy każdym znaczniku czasu?
Kilka pomysłów/poprawki w moim umyśle:
- ustawiona amplituda przez coraz uśrednionego/max szacunkową wartość amplitudy z sygnału w dziedzinie czasu oryginalnego utworu.
- Całkowicie zmień moje podejście --- oblicz spektrogram/krótkoterminową fourierową transformację sygnału audio utworu. odcinanie prawie/zero-out lub cicho wszystkie inne częstotliwości, z wyjątkiem tych w mojej pitch-track (lub są zbliżone do mojego pitch-track). Następnie obliczyć odwrotną krótkoterminową transformatę Fouriera, aby uzyskać sygnał w dziedzinie czasu.
Możesz stworzyć midi, który ma takie same wysokości/pochylenia/czasy/czasy, co twoja melodia, wybierz odpowiedni instrument i wyrenderuj go w wybranym programie/bibliotece. alternatywnie, można było nadać każdej nucie obwiednię amplitudy, która zaczyna się silnie (albo buduje się od zera szybko, albo zaczyna silny), zmniejsza się do trzymanej w milczeniu ilości i kończy na końcu. Nazywa się to kopertą ADSR. – Patashu
Jakoś mój nowy stolik jako projekt domowy nie jest imponujący. -1 za sprawienie, że poczułam się jak Igor jaskiniowiec (tylko żartuję). –