Fourier transformu ile resample - [ Bulmaca, ödev, yarışma :) ]

Başlatan t2, 18 Eylül 2016, 16:58:34

t2


Sinyalleri yazılımsal olarak  yeniden örnekleme  (upsample, resample) yapmak mümkün.
http://dspguru.com/dsp/faqs/multirate/resampling

Örneğin 8khz ses dosyasını 16khz örneklenmiş yüksek kaliteli kayıt gibi yapmak istersek, her örneği kopyalıyoruz. bu şekilde 16khz dosya elde ediliyor. Windows, aynen  bu şekilde uyduruk dönüşüm yapıyor. 

Biraz daha iyisi, önceki ve sonraki örneği toplayıp ikiye bölmek araya yeni örnek olarak eklemektir.  fakat yine uyduruk oluyor.

Fakat pofesyonel ses işleme programları bu işi daha güzel yapıyor.  işin aslı Fourier transformu ile yeniden dalga oluşturmak imiş. fakat nasıl yapıldığını anlayamadım.


Aşağıdaki sayfada anlatılmış. anlayıp da izah ediverirseniz hep beraber öğrenmiş oluruz

https://ccrma.stanford.edu/~jos/resample/


pdf olarak indir:

https://ccrma.stanford.edu/~jos/resample/resample.pdf


Dalgayı Fourier  transformu yaptık . elimizde her frekans için genlik değerleri var. bunları nasıl işleyeceğiz.? hangilerini atlayıp hangilerini toplayacağız ki yeni ve yüksek örnekleme değierine sahip diziyi elde edelim?

Bir seferlik iş olsa ses işleme programları ile yapılır. fakat program içerisine gömmek istiyorum.

alicavuslu

Interpolasyon filtreyi araştırmanızı öneririm. Bahsettiğiniz işlemleri zaman düzleminde yapmanızı sağlıyor.

t2

Belirttiğim sayfada anlatılıyor da ben anlayamadım.
Fourier transformu yapabilecek  kod parçacıklarını temin ettim. spektrum elde edebiliyorum. bu genlik değerlerini öyle bir işlemden geçireceğiz ki yeniden örneklemiş gibi başka bir dalga elde edilecek. Tüm frekans bileşenlerini toplarsak galiba dalganın kendisini aynen elde ediyoruz. zaten Fourier transformu mantığı budur. Bir sinyal yüksek frekanslı sinüs dalgaların toplamından oluşuyor. Yüksek frekanslı dalgalar elimizde var diyelim. örnekleme ile alakasını nasıl oluşturacağız?   

alicavuslu

FFT kullanarak yapılacak işlem sırasına ait MATLAB kodları aşağıdadır.

İlk şekil 16 ile orneklenmiş 1 Hz lik sinüs diğeri ise 32 ile örneklemiş 1 Hzlik sinüsü göstermektedir.

FFT ile bu işlemleri yapafcaksanız overlap olayınıda araştırmanız gerekmektedir.

clc, clear all, close all;

f_s = 16;
f_g = 1;

n_t = 1 : 16;

Giris = sin(2 * pi * f_g * n_t / f_s);
figure, plot(Giris);

giris_fft = fft(Giris, f_s);
giris_fft_new = zeros(1, 32);
giris_fft_new = 2*[giris_fft(1:8) ...
    zeros(1,16) giris_fft(9:16)];

giris_new = real(ifft(giris_fft_new, 32));
figure, plot(giris_new);

t2

Sağol. fakat matlab bilgim sıfır. hiç kullanmadım. Delphi ile program yazıyorum. Wav dosyayı stream olarak bayt bayt okuyup spektrum elde edebilirim.

matlab koduna baksam acaba yorum yapsam durum ne olur.
giris_fft_new = zeros(1, 32); ne demektir? yeni şekil ve fft başlat? olsa gerek. peki zeros ne ?

real(ifft(giris_fft_new, 32)); kısmı ile galiba tersFFT yapılıyor. fft dizisinden asıl diziyi elde ediyoruz değil mi? elimde inverse FFT rutini de vardı. bunlardan  bir netice alabilirim sanırım. FFT dizisinden bazı elemanları çıkarıp  yeni dizi elde etmek için IFFT mi yapıyoruz? veya çıkarmadan parametre değişimi ile mi yapıyoruz? bu kısmı anlayabilsem delphi kodunu uyarlayabilirim.


hocam elimdeki demo kod şöyle çalışıyor. 3 tane farklı sinüs dalgası var.  bunların genliklerini toplayıp yeni genlik elde ediyoruz. N sayıları aynı.  1. diziden 1. genlik. 2. diziden 1. genlik... toplanarak yeni dizinin 1. genliği bulunuyor. 

Bu şimdi  tek bir dizidir. bu diziyi FFT yaptığımızda bu 3 farklı  sinüs   için spektrum aynen çıkıyor. ayarladığımız genlikler elimizde. fakat ilk orijinal dalgayı bu genliklerden nasıl oluşturacağız? hem de öyle bir ayar yapılacak ki örnekleme frekansı değişecek. aradaki örnekler de ortaya çıkacak?

alicavuslu

Sizi ilgilendiren kısım FFT'yi aldıktan sonra giris_fft_new = 2*[giris_fft(1:8)  zeros(1,16) giris_fft(9:16)]; işlemini yapmak. Görülceği üzere ilk kısma fft'nin ilk parçasını yazıyorz. Daha sonra kaç ile genişletecek isek FFT uzunluğunun katı kadar sıfır ekliyoruz. 2 kat için 1 FFT boyu ekledik. 3 kat için 2 FFT boyu sıfır ekleyecektirk. Son kısmada FFT'nin kalan kısmını ekliyoruz. Real işlemi ise inverse FFT sonrasında gerçel kısmı almamızı sağlıyor. Birde genlik normalizasyonu için kaç ile genişletecek isek onun ile çarpıyoruz. 2'nin amacı budur.


t2

Anlayamadım malesef,  elimizde 8khz örneklenmiş tek dalga var bunu genişletmek ve yeniden 16khz örneklenmiş gibi oluşturabilmek için işlem sırasını öğrenebilir miyim?

Orijinal dalga  tam sinüs değil. hangi bileşenlerden oluşmuş bilmiyoruz.
Dalga değişecek çünkü. ses dalgası? konuşma sesi olsun. Düşük kaliteli yapılmış kaydımızı, yüksek kaliteli formata çeviriyoruz. (kalite artış umudum yok. sadece formatı düzgün çevirelim yeter.)
Hocam demo amaçlı wav dosyayı da şuraya yükledim. sizde matlab varsa  bu upsample işlemini yapabilir misiniz? 16khz örneklenmiş yeni dosya elde edilecek.   işlem başarıyla bittikten sonra gerekli matlab kodunu burada paylaşırsanız, kodu anlamak ve delphiye uyarlamak için yeniden rahatsız edebilirim

Teşekkür ederim.

Deneme test wav dosya:
http://uppit.com/aqpnq9c4optx





alicavuslu

2 türlü bu işlemi yapabilirsiniz. 1. si FFT'li olan. İşlem sırası şu şekilde:
FFT'yi alırız.
2 Katına çıkaracak ise FFT'nin boyunun 2 katı katar uzunlukta bir dizi oluşturup tüm değerlerine sıfır atanır
Yeni dizinin ilk kısmına FFT'nin FFT'uzunluğunun yarısı kadar olan değerleri yazarız.
Daha sonra FFT'nin son kısmını yeni dizinin sondan FFT'uzunluğunun yarısı kadar olan değerleri yazarız.
Inverse FFT'nin gerçel kısmını alırız.

2. İşlemde ise dizide yukarı örnekleme için kaç kata çıkacak isenin bir eksiği kadar sıfır eklenir. [1 2 3] değerlerini 2 katına çıkarmak için [1 0 2 0 3] şeklinde olacak.
Interpolasyon filtre katsayılarını bulmanız gerekcektir. MATLAB'da bunun için hazır komut var
Bu katsayılar ile konvolüsyon işlemi yapacaksınız.


t2

Sağol varol. hocam  yukarıda 8k wav dosyayı yükledim. sizin için kolay bir işlem gibi görünüyor. kesin işlemleri sırayla yapıp bana matlab kodunu iletiverseniz?  oradan bakıp çalışayım? teşekkürler. saygılar.

alicavuslu

Aşağıki gibi kodları gerçekleştirebilirsiniz.

clc, clear all; close all;

[Data f_s] = audioread('test8k.wav');
figure, plot(Data);
Data_new = zeros(1, length(Data))
for n_i = 1 : length(Data)
    Data_new(2 * n_i - 1) = Data(n_i);
end

%% Bu katsayılar sizin değerlerinize göre ayarlanıyor.
Coeff = intfilt(1, 2, 0.5);

Data_new = filter(Coeff, 1, Data_new);
figure, plot(Data_new);
audiowrite('test16k.wav', Data_new, 2 * f_s)

t2

Hocam,  örnek kopyalama,  araya sıfır ekleme yöntemi yerine,  fft olanı yapmam lazım. 
Galiba daha iyi olacak. Karecikler sanki düzelecek diye umuyorum.

alicavuslu

Hocam buda aynı işi yapıyor. Biri frekans düzleminde biri zaman düzleminde. İşlem açısından size daha avantaj sağlayacaktır.

t2

Peki bu yöntem,  ilk mesajda bildirdiğim makaledeki ile aynı mıdır?
Aynı yöntemi kullanan uygulamalar denemiştim güzel  çeviriyor.  Örnek Audacity.

alicavuslu

Çok emin olmamak ile birlikte benzer bir yöntemdir diyebilirim. Açıkçası ben sesleri dinlediğimde çevrim işlemi başarılı duruyor..

z

@alicavuslu

FFT nin iki katı datalar kullanmak amacıyla araya sıfırlar koymakla iki sample arasına örnekleme frekansında bir sinüs geçişi yapmış olmuyor muyuz. Bunun sese nasıl bir renk katmasını bekleyebiliriz?

@t2

Bir ara FFT videoları hazırlamış ve bir tane de exe program yayınlamıştım.

Onda sinyalle grafiksel olarak oynanabiliyordu diye hatırlıyorum. Sanki fikir verebilir gibi. (Yanlış da hatırlıyor olabilirim)
Bana e^st de diyebilirsiniz.   www.cncdesigner.com