Goto page Previous 1, 2
sundayman
Guest
Fri Jul 05, 2013 11:22 pm
no bardzo koledze dziękuję, zaraz spróbuję to użyć, tylko
mam obawę, czy to się da zastosować do pliku audio, który ma np 10 sekund ?
No bo właśnie o to chodzi - o efekt "globalny", że tak to powiem.
Cała ta procedura istotnie zmienia "obwiednię" takiego sygnału (uśrednia
ją bardzo przyjemnie właśnie), no i to chcę pokazać, ale
na całym sygnale, a ten ma około 10 sekund...
Ok, próbuję...
sundayman
Guest
Sat Jul 06, 2013 12:08 am
W dniu 2013-07-05 23:57, Michał Lankosz pisze:
Quote:
Skrypt Octave, krok po kroku:
No żesz kuśwa - rewelka !
Sprawdziłem na pierwszym skrypcie, znaczy :
[data,fs] = wavread("audio.wav");
n=30;
b = ones(n,1)./n;
y = filter(b,1,data);
wavwrite(y,"wynik.wav");
_____________________________________________________________________
to jest właśnie to, o co chodzi ! Znaczy prawie...

Ale o tym zaraz.
Natomiast - generalnie działa super.
Zapodałem sobie pliczek, octave go przerobiło, i wynikowy pliczek mogę
sobie już odsłuchać, oglądać itp.
Natomiast muszę jeszcze poprosić o dalszą pomoc
Bo trochę uprościłem wstępny opis, licząc, że potem sam sobie dam z tym
radę. No ale jak widać nie bardzo...
Więc - faktycznie cały proces obróbki wygląda tak ;
Najpierw sygnał audio jest prostowany (analogowo) w dwupołówkowym
prostowniku (na OPAMPie).
Następnie - sygnał trafia do przetwornika A/D, gdzie jest próbkowany z
częstotliwością 1kHz, a następnie ;
Z każdych kolejnych 10-ciu próbek (1-10, 11-20, 21-30, czyli nie "w
kółko", jak podczas uśredniania, tylko zwyczajnie, po kolei każde 10 )
wybierana jest największa próbka.
I dopiero te dane podlegają opisanemu już uśrednieniu.
Efekt samplowania w przetworniku A/D można pominąć , bo to chyba można z
przybliżeniem zrobić odpowiednio "resamplując" oryginalny plik audio.
Czyli potrzebne jest ostatecznie :
1. prostowanie sygnału
2. wybór największej próbki z kolejnych 10-ciu
3. uśrednianie wg. wcześniejszej procedury
Da się tak zrobić ??
sundayman
Guest
Sat Jul 06, 2013 12:14 am
Quote:
Czyli potrzebne jest ostatecznie :
1. prostowanie sygnału
2. wybór największej próbki z kolejnych 10-ciu
3. uśrednianie wg. wcześniejszej procedury
Da się tak zrobić ??
Żeby nie było, że nie próbuję, ściągnąłem helpa do octave, i popróbuję
gdzieś tak do 5 rano :)
Tak czy owak będę musiał się tego nauczyć (choć pewnie zajmie to trochę
czasu), bo to bardzo przydatne narzędzie - często muszę przetwarzać
sygnały w takie dziwne sposoby, i ten soft jest jak znalazł.
PureData też zresztą.
Ech, żeby tak można jak w "matrixie" załadować sobie w 10 sekund
umiejętność obsługi
Luke
Guest
Sat Jul 06, 2013 7:10 am
Quote:
no patrz, nie wiedziałem, że to ma taką mądrą nazwę :)
Ale wiedziałeś i żartujesz, czy nie wiedziałeś? Bo Savitzky-Golay to
jest filtr, który uśrednia próbkę przez dopasowanie wielomianu do
kawałka sygnału. Jeśli wielomianem jest prosta, to jest to równoznaczne
(poza krańcami sygnału) z uśrednianiem.
A jako że do R i Matlaba masz funkcje gotowe do tego filtru, to np.
Quote:
library(signal)
Loading required package: MASS
Attaching package:
Michał Lankosz
Guest
Sat Jul 06, 2013 7:13 am
W dniu 2013-07-06 02:08, sundayman pisze:
Quote:
to jest właśnie to, o co chodzi ! Znaczy prawie...
[...]
Natomiast muszę jeszcze poprosić o dalszą pomoc
Czyli potrzebne jest ostatecznie :
1. prostowanie sygnału
2. wybór największej próbki z kolejnych 10-ciu
3. uśrednianie wg. wcześniejszej procedury
Da się tak zrobić ??
Da się, nie ma problemu. Może z dalszą pomocą w postaci kolejnych wersji
programu przejdę na priv. Tylko nie teraz
Na szybko kilka wskazówek, może sobie sam poradzisz:
prostowanie sygnału:
data1 = abs(data);
największa próbka z 10-ciu kolejnych (pętla for, może da się ją ominąć?):
data2 = max(data1(i:i+10));
liczby rozdzielone dwukropkiem oznaczają przedział
tylko że trzeba w pętli ten wektor sklejać, tzn za każdym obiegiem pętli
doklejać kolejną wartość, coś w rodzaju:
data3 = [];
for i=1:10:data_length % i inkementuje się co 10!
data2 = max(data1(i:i+10));
data3 = [data3, data2];
endfor
no i teraz już ten filter.
Dla sprawdzenia możesz w każdym miejscu wpisać plot(data3) na przykład i
zobaczyć dany wykres. Dla dużej liczby próbek na wykresie można
zrezygnować z kropek danych, zostawić tylko linie
plot(t,y,"g-"); t-wektor czasu, a właściwie to numer próbki, y dane,
g to kolor, - to rysowanie linią. "g:" narysuje Ci kropkowany wykres, a
"g--" linią przerywaną.
--
Michał
sundayman
Guest
Sat Jul 06, 2013 9:45 am
W dniu 2013-07-06 09:13, Michał Lankosz pisze:
Quote:
W dniu 2013-07-06 02:08, sundayman pisze:
to jest właśnie to, o co chodzi ! Znaczy prawie...
[...]
Natomiast muszę jeszcze poprosić o dalszą pomoc
Czyli potrzebne jest ostatecznie :
1. prostowanie sygnału
2. wybór największej próbki z kolejnych 10-ciu
3. uśrednianie wg. wcześniejszej procedury
Da się tak zrobić ??
Da się, nie ma problemu. Może z dalszą pomocą w postaci kolejnych wersji
programu przejdę na priv. Tylko nie teraz
Na szybko kilka wskazówek, może sobie sam poradzisz:
prostowanie sygnału:
data1 = abs(data);
największa próbka z 10-ciu kolejnych (pętla for, może da się ją ominąć?):
data2 = max(data1(i:i+10));
liczby rozdzielone dwukropkiem oznaczają przedział
tylko że trzeba w pętli ten wektor sklejać, tzn za każdym obiegiem pętli
doklejać kolejną wartość, coś w rodzaju:
data3 = [];
for i=1:10:data_length % i inkementuje się co 10!
data2 = max(data1(i:i+10));
data3 = [data3, data2];
endfor
no i teraz już ten filter.
Dla sprawdzenia możesz w każdym miejscu wpisać plot(data3) na przykład i
zobaczyć dany wykres. Dla dużej liczby próbek na wykresie można
zrezygnować z kropek danych, zostawić tylko linie
plot(t,y,"g-"); t-wektor czasu, a właściwie to numer próbki, y dane,
g to kolor, - to rysowanie linią. "g:" narysuje Ci kropkowany wykres, a
"g--" linią przerywaną.
fantastycznie, spróbuję toto poskładać.
Tylko najpierw niestety muszę odwalić pańszczyznę...
WIFE> CONFIG SUNDAYMAN(VACUUM CLEANER, FAST)
WIFE> CALL CLEANING(ALL_ROOMS)
WIFE> SETUP SPEED=ULTRAHIGH
WIFE> SOUND=OFF ' SILENCE MODE/MORDA_W_KUBEŁ
itp...
Miroslaw Kwasniak
Guest
Sat Jul 06, 2013 10:02 am
Michał Lankosz <mike2001@tlen.pl> wrote:
Quote:
największa próbka z 10-ciu kolejnych (pętla for, może da się ją ominąć?):
data2 = max(data1(i:i+10));
i:i+10 to też pętla

Ale ukryta - taki zabieg nazywamy w octave/matlabie
wektoryzacją zagadnienia.
Quote:
liczby rozdzielone dwukropkiem oznaczają przedział
tylko że trzeba w pętli ten wektor sklejać, tzn za każdym obiegiem pętli
doklejać kolejną wartość, coś w rodzaju:
data3 = [];
for i=1:10:data_length % i inkementuje się co 10!
data2 = max(data1(i:i+10));
data3 = [data3, data2];
endfor
no i teraz już ten filter.
Modyfikacje Twojego rozwiązania:
1) Polecenia "data3 = []" i "data3 = [data3, data2]" to wygodny zapis dla
nieznanej długości data3, ale kosztują: w każym obiegu pętli wykonujesz
dodatkowo niepotrzebne operacje:
-- utwórz nową tablicę data3 o długości length(data3)+1
-- skopiuj starą do nowej
-- skasuj starą
Remedium: prealokacja tablicy
L=floor(length(data1)/10);
data3=zeros(1,L);
for i=1:L
data3[i]= max(data1((i-1)*10+(1:10)))
endfor
2) Na ogół 10<L, więc lepiej zmienić kolejność jawnej i niejawnej pętli,
jawne (czyli niezwektoryzowane) wykonują się wolniej
Remedium poniżej (przy założeniu, że data1 jest wektorem kolumnowym);
ii=1:10:length(data1);
data3=data1(ii).';
for i=1:9
data3=max([ data3; data1(i+ii).' ]);
endfor
3) Obie pętle można w tym zagadnienu zwektoryzować, ale tu opłacalność
pewnie żadna, a czytelność kodu spada:
l=length(data1);
i=ones(10,l/10);
i(1,

=1:10:l;
i=cumsum(i);
data3=max(data1(i));
clear i;
Michał Lankosz
Guest
Sat Jul 06, 2013 11:16 pm
W dniu 2013-07-06 10:02, Miroslaw Kwasniak pisze:
Quote:
1) Polecenia "data3 = []" i "data3 = [data3, data2]" to wygodny zapis dla
nieznanej długości data3, ale kosztują: w każym obiegu pętli wykonujesz
2) Na ogół 10<L, więc lepiej zmienić kolejność jawnej i niejawnej pętli,
jawne (czyli niezwektoryzowane) wykonują się wolniej
3) Obie pętle można w tym zagadnienu zwektoryzować, ale tu opłacalność
pewnie żadna, a czytelność kodu spada:
Wszystko racja lub zapewne racja. Wyszedłem z wprawy, do tego dochodzą
naleciałości z C. Myślę, że dla sundymana moje przykłady mogą być
bardziej przejrzyste, chociaż zdaję sobie sprawę z kiepskości tej
implementacji.
Najmocniejszą stroną Matlab/Octave są operacje na macierzach, dlatego na
wszelkie obliczenia trzeba odpowiednio popatrzeć... jak w Matrixie
Nie jest to bardzo trudne, wymaga tylko pewnej wprawy.
Quote:
data3=data1(ii).';
Kropka w większości przypadków wiem co robi. Apostrof transponuje
macierz/wektor. Ale .' nie kojarzę.
--
Michał
sundayman
Guest
Sun Jul 07, 2013 1:06 am
Zrobiłem tak ;
data =
[2,6,3,8,4,6,15,20,40,20,25,98,17,34,5,23,5,3,35,44,23,17,19,16,2,3,8,4,7,4];
len = length(data);
data1 = abs(data)
data3 = [];
a=3; % ilość próbek do wartości max
for i=1:a:length(data1)
data2 = max(data1(i:i+(a-1)));
data3 = [data3, data2];
endfor
% uśrednianie
n=2; % ilość próbek uśredniania
b = ones(n,1)./n;
y = filter(b,1,data3);
t = [1:length(data1)];
%plot(t,data1,"b*-")
t2 = [1:length(data3)];
plot(t,data1,"b*-", t2*a,y, "r*-")
____________________________________________
na razie na danych ręcznie wpisanych, żeby sprawdzić.
No i chyba - kuśwa działa !

)
Jutro spróbuję na wav.
Miroslaw Kwasniak
Guest
Sun Jul 07, 2013 12:43 pm
Michał Lankosz <mike2001@tlen.pl> wrote:
Quote:
data3=data1(ii).';
Kropka w większości przypadków wiem co robi. Apostrof transponuje
macierz/wektor. Ale .' nie kojarzę.
Nie, .' jest transpozycją, a sam apostrof to
http://pl.wikipedia.org/wiki/Sprzężenie_hermitowskie_macierzy
Co dla macierzy rzewywistych niczym się nie różni
sundayman
Guest
Sun Jul 07, 2013 1:40 pm
Quote:
Wszystko racja lub zapewne racja. Wyszedłem z wprawy, do tego dochodzą
naleciałości z C. Myślę, że dla sundymana moje przykłady mogą być
bardziej przejrzyste, chociaż zdaję sobie sprawę z kiepskości tej
implementacji.
Tak jest właśnie - jest to dla mnie ciut bardziej zrozumiałe
Jak napisałem, na ręcznie wprowadzonych danych generalnie jest ok,
natomiast przy próbie wygenerowania WAV już jest gorzej.
Mam tak :
[data,fs] = wavread("audio.wav");
%data =
[2,6,3,8,4,6,15,20,40,20,25,98,17,34,5,23,5,3,35,44,23,17,19,16,2,3,8,4,7,4];
len = length(data);
data1 = abs(data)
data3 = [];
a=10; % ilość próbek do wartości max
for i=1:a:length(data1)-a
data2 = max(data1(i:i+(a-1)));
data3 = [data3, data2];
endfor
% uśrednianie
n=2; % ilość próbek uśredniania
b = ones(n,1)./n;
y = filter(b,1,data3);
wavwrite(y,"wynik.wav");
%t = [1:length(data1)];
%plot(t,data1,"b*-")
%t2 = [1:length(data3)];
%plot(t,data1,"b*-", t2*a,y, "r*-") % to odblokować
%stem(t,[data', y']);
***************************
i teraz, dla a=10 jak powyżej, wywala mi błąd, że
"Y has more than 32767 columns, too many for WAV-file"
tego akurat nie rozumiem. Znaczy chodzi o to, że wartość wykracza poza
dopuszczalne 16 bitów ? Ale jakim cudem, bo przecież nie powinno być
więcej niż jest maksymalnie w audio.wav ?
Jak zwiększę a=100 to wtedy niby generwuje ten WAV, ale nie daje się on
otworzyć. Wieczorem spróbuję powalczyć, bo w sumie to chciałbym zrobić
tak, żeby niezależnie od wyboru "a" i "n" WAV wygenerowany był takiej
samej długości jak źródłowy.
Czyli trzeba by powielać dane wyjściowe i posklejać je w jeden wav.
Próbki będą znaczy się powtarzać, ale dzięki temu będzie można
ładnie porównać obie "fale" i posłuchać także..
Michał Lankosz
Guest
Sun Jul 07, 2013 4:59 pm
W dniu 2013-07-07 15:40, sundayman pisze:
Quote:
"Y has more than 32767 columns, too many for WAV-file"
Kolejne próbki mają być w kolejnych wierszach, dwie kolumny to sygnał
stereo. Czyli wpisz:
wavwrite(y.',"wynik.wav");
Poczytaj o wavwrite, bo domyślnie wstawia w nagłówku częstotliwość
próbkowania 8kHz, a można wymusić inną.
--
Michał
sundayman
Guest
Mon Jul 08, 2013 1:29 am
Ostatecznie mam takie coś :
[data,fs] = wavread("audio.wav");
%data =
[2,6,3,8,4,6,15,20,40,20,25,98,17,34,5,23,5,3,35,44,23,17,19,16,2,3,8,4,7,4];
len = length(data);
data1 = abs(data)
data3 = [];
a=44; % ilość próbek do wartości max
for i=1:a:length(data1)-a
data2 = max(data1(i:i+(a-1)));
data3 = [data3, data2];
endfor
% uśrednianie
n=30; % ilość próbek uśredniania
b = ones(n,1)./n;
y = filter(b,1,data3);
% składanie WAV
data4 = [];
for i=1:length(y)
probka = y(i:i);
for j=1:a
data4 = [data4,probka];
endfor
endfor
wavwrite(data4.', 44100 , "wynik_n30.wav");
*************************************
No muszę powiedzieć - działa
Nawet chyba udało mi się zrobić, żeby wynikowy wav miał tą samą
długość,co wejściowy (rozciągnąłem po prostu z tym samym
współczynnikiem, o który się skraca w wyniku znajdowania wartości
maksymalnej).
Teraz mogę sobie testować w te i wefte na różnych parametrach - no coś
pięknego. I z tego co widzę, to się nawet chyba zgadza z empirią :)
Panie Michale, jest pan wielki ! Zazdroszczę znajomości tego narzędzia -
coś mi cholerycznie ciężko nad tym zapanować, ale warto się pomęczyć.
Tak że - słów podziękowań brak mi po prostu :)
Oczywiście pozostałym kolegom także dziękuję bardzo.
*************************************
Na wszelki wypadek zapytam jeszcze na koniec ;
jak widać zmieniłem tą linię :
data2 = max(data1(i:i+a))); * gdzie oczywiście "a" to przedział
szukania maximum (zastąpiłem "10" z przykładu kolegi zmienną "a" , żeby
mieć łatwiej w razie zmian wartości)
na następującą wersję :
data2 = max(data1(i:i+(a-1)));
bo wydaje mi się, że w wersji "źródłowej" robi się zakres o 1 za duży
(np. dla przedziału 10 zakres byłby 10:20 zamiast wymaganego 10:19).
Wygląda mi to na po prostu drobną pomyłkę kolegi, ale wolę się upewnić -
czy wszak dobrze zrobiłem ?
Michał Lankosz
Guest
Mon Jul 08, 2013 6:15 am
W dniu 2013-07-08 03:29, sundayman pisze:
Quote:
Panie Michale, jest pan wielki ! Zazdroszczę znajomości tego narzędzia -
coś mi cholerycznie ciężko nad tym zapanować, ale warto się pomęczyć.
Ja już bardzo dużo zapomniałem. Matlab to wielkie narzędzie! Fajnie, że
ma darmowy odpowiednik, a przynajmniej namiastkę.
Quote:
[...]
bo wydaje mi się, że w wersji "źródłowej" robi się zakres o 1 za duży
(np. dla przedziału 10 zakres byłby 10:20 zamiast wymaganego 10:19).
Wygląda mi to na po prostu drobną pomyłkę kolegi, ale wolę się upewnić -
czy wszak dobrze zrobiłem ?
Tak, błąd. Zawsze możesz sprawdzić na danych testowych. W linii poleceń
wpisujesz nazwę zmiennej i wyświetla Ci jej wartość (skalar, wektor,
macierz). Size(x) podaje rozmiar. A widzisz, gdybyś miał plik wave
stereofoniczny do wavread do data1 wpisze macierz, dwie chyba kolumny
kanałów. Żeby wyciągnąć jedną kolumnę piszesz:
chan1 = data1(:,1)
gdzie 1 wybiera pierwszą kolumnę.
Świetnie! Widzę, że dalej już sam sobie poradzisz :)
--
Michał
Goto page Previous 1, 2