2017-06-22 84 views
6

Potrafię przesunąć cały sygnał za pomocą resample i wypróbowałem kod wokodera fazowegohere.Przyrostowo/stopniowo zmieniaj skok sygnału w czasie, używając kodu oktawowego/matlab

Próbowałem zostały również repmat and interpolation i zajrzałem do fft and interp1

Jak mogę narastająco/stopniowo zmienić wysokość sygnału w czasie? Dołączyłem przykład z Original Signal i staram się brzmieć tak, jak brzmiał Processed Signal (stworzyłem przetwarzany sygnał za pomocą Audacity i używając ich efektu Sliding time scale/pitch shift). Ale chciałbym stworzyć ten sygnał w Octave 4.0. Jeśli słuchasz Processed Signal, możesz stopniowo zwiększać wysokość pliku, ale plik ten ma taką samą długość (w sekundach) co plik Original Signal.

Używam Octave 4.0, która jest jak Matlab

Oto kod, który może zmienić wysokość całego sygnału i zachować tę samą długość oryginalnego sygnału w sekundach, ale nie jestem pewien, jak niech stopniowo zmieni on wysokość sygnału w czasie. Podziękowania dla rayryeng za doprowadzenie mnie do tego miejsca.

clear, clc 
[ya, fs, nbitsraw] = wavread('/tmp/original_signal.wav'); 

num_per_sec=2.4; %// Define total number of times we see the signal 

%// Get total number of integer times we see the signal 
num_whole = floor(num_per_sec); 

%// Replicate signal 
yb=repmat(ya,num_whole,1); 

%// Determine how many samples the partial signal consists of 
portion = floor((num_per_sec - num_whole)*length(ya)); 

%// Sample from the original signal and stack this on top of replicated signal 
yb = [yb; ya(1:portion)]; 

%interpolation 
xxo=linspace(0,1,length(yb))'; 
xxi=linspace(0,1,length(ya))'; 
yi_t=interp1(xxo,yb,xxi,'linear'); 

wavwrite([yi_t'] ,fs,16,strcat('/tmp/processed_signal.wav')); % export file 
+0

Ponieważ wydaje się, że jesteś zainteresowany robieniem tego dla sygnałów mowy, możesz chcieć przyjrzeć się analizie/narzędzia do resyntezy, takie jak [PSOLA] (https://en.wikipedia.org/wiki/PSOLA).Takie narzędzia powinny dawać znacznie bardziej naturalną zmianę wysokości tonu. (Zauważ, że PSOLA jest dość długa w zębach - obecnie może być lepsza alternatywa). –

+0

audacity używa biblioteki [sbsms] (https://sourceforge.net/projects/sbsms/) do modelowania sinusoidalnego podpasma. Jeśli chcesz może przepisać wszystko w MATLAB/Octave, albo skompilować je i użyć jako mex/oct – rahnema1

Odpowiedz

6

Moja odpowiedź nie daje dokładnie taki sam wynik jak ten, który pisał, ale myślę, że to ciekawe i na tyle prosty, aby dać Ci ważnych pojęć za pitch rozciągania. Nie znalazłem metody, którą proponuję gdzie indziej w sieci, ale nie mogę sobie wyobrazić, że nikt wcześniej o tym nie myślał, więc może mieć imię.

Pierwszą rzeczą, aby zdać sobie sprawę, że jeśli chcemy zastosować transformacje na boisku z czasem, a nie tylko przesunięcie go na całej timecourse, trzeba pracować z pitch „funkcje”, które są zdefiniowane na siebie time-point (np. transformacje czasowo-częstotliwościowe), w przeciwieństwie do tych, które podsumowują całą treść sygnału (np. Fourier).

Ważne jest, aby uświadomić sobie to, bo to staje się oczywiste, że musimy zaangażować rzeczy jak chwilowej częstotliwości swojego sygnału, który jest defined as pochodna fazy Hilbert (zwykle traktowanych jako (1/2Pi) * dPhi/ dt pracować w Hz zamiast rad/s).

Zakładając, że możemy przekształcić chwilową częstotliwość sygnału, możemy przełożyć ideę „zwiększenie skoku stopniowo” formalnie do „dodanie liniowo zwiększający się przesunięcie do chwilowej częstotliwości”. Dobra wiadomość jest taka, że ​​możemy łatwo przekształcić chwilową częstotliwość sygnału, używając analytic transform. Oto jak:

function y = add_linear_pitch(x, fs, df) 
% 
% y = add_linear_pitch(x, fs, df) 
% 
% x, fs: audio signal (1-dimensional) 
% df: the amplitude of frequency offset, in Hz 
% 
% See also: hilbert 
% 

    x = x(:); 
    n = numel(x); % number of timepoints 
    m = mean(x); % average of the signal 
    k = transpose(0:n-1); 

    h = hilbert(x - m); % analytic signal 
    e = abs(h); % envelope 
    p = angle(h) + df*pi*k.^2/fs/n; % phase + linearly increasing offset 
    y = m - imag(hilbert(e .* sin(p))); % inverse-transform 

end 

Jedynym nieoczywisty rzeczą w poprzednim kodzie jest to, że musimy się zintegrować „liniowo rosnącą boiska offset” (lub cokolwiek transformacja chwilowej częstotliwości) przed zastosowaniem go w fazie, i pomnóż go przez 2Pi (do pracy w radianach). W naszym przypadku całka funkcji liniowej jest po prostu funkcją kwadratową, ale można grać z bardziej skomplikowanymi rzeczami :)

+0

To jest naprawdę eleganckie czy istnieje sposób na obliczenie prawidłowego nachylenia, jeśli chcę skończyć z określoną częstotliwością? Przykładem może być sytuacja, w której pierwotny sygnał głosowy miał maksymalną częstotliwość rezonansową 326,8 Hz i chciałbym, aby kończył się przy 402,3 Hz? –

+1

Myślę, że to możliwe, powinno zależeć tylko od różnicy częstotliwości (delta-y) i długości sygnału (delta-x). Jestem zajęty w bankomacie, ale pomyślę o tym więcej i zredaguję mój wpis w ciągu kilku dni. – Sheljohn

+0

Umieściłem to pytanie w sekcji matematycznej, czy ta formuła jest przydatna? https://math.stackexchange.com/posts/comments/4816923?noredirect=1 –