मैं "विंडो फ़ंक्शन" के लिए शॉर्टहैंड विंडो का उपयोग करूंगा ।
ऑडियो के साथ, कोई भी प्रोसेसिंग जो प्री-रिंगिंग या प्री-इको के लिए कुछ समान बनाता है, कम बिट-रेट mp3 की तरह धीमी आवाज करेगा। यह तब होता है जब एक क्षणिक या आवेग की स्थानीयकृत ऊर्जा समय में पीछे की ओर फैल जाती है, उदाहरण के लिए लैपेड ट्रांसफ़ॉर्म में मैपेड डेटा द्वारा संशोधन जैसे कि लैप्स संशोधित असतत कोसाइन ट्रांसफ़ॉर्म (एमडीसीटी)। इस तरह के प्रसंस्करण में, विश्लेषण खिड़कियों को ओवरलैप करके ऑडियो को विंडो किया जाता है , रूपांतरित किया जाता है, फ़्रीक्वेंसी डोमेन में संसाधित किया जाता है (जैसे डेटा को एक छोटी बिटरेट पर संपीड़ित किया जाता है), फिर से एक संश्लेषण खिड़की के साथ खिड़की और एक साथ वापस बुलाया। विश्लेषण और संश्लेषण खिड़की का उत्पाद ऐसा होना चाहिए जो अतिव्यापी खिड़कियां एकता के लिए योग करें।
परंपरागत रूप से उपयोग किए जाने वाले खिड़की के कार्य सममित थे, और उनकी चौड़ाई आवृत्ति चयनात्मकता (लंबी खिड़की) और समय-क्षेत्र विरूपण साक्ष्य परिहार (छोटी खिड़की) के बीच एक समझौता रही है। खिड़की जितनी चौड़ी होगी, प्रसंस्करण में उतनी ही अधिक समय तक सिग्नल फैल सकता है। एक और हालिया समाधान एक असममित खिड़की का उपयोग करना है। उपयोग की जाने वाली दो खिड़कियां एक दूसरे की दर्पण छवियां हो सकती हैं। विश्लेषण खिड़की शिखर से शून्य तक तेजी से गिरती है ताकि आवेगों को पहले से "अधिक" पता न चले, और सिंथेसिस खिड़की शून्य से शिखर तक तेजी से बढ़ जाती है, ताकि किसी भी प्रसंस्करण का प्रभाव समय में बहुत पीछे न फैले। इसका एक अन्य लाभ कम विलंबता है। विषम खिड़कियों में अच्छी आवृत्ति-चयनात्मकता हो सकती है, और ऑडियो संपीड़न में चर-आकार की सममित खिड़कियों को बदल सकते हैं, एक तरह का इलाज-सभी की तरह। देखएम। श्नेल, एम। श्मिट, एम। जैंडर, टी। अल्बर्ट, आर। गीगर, वी। रूपोपिला, पी। एकस्ट्रैंड, एम। लुत्ज़की, बी। ग्रिल, "MPEG-4 एन्हांस्ड लो डिले एएसी - हाई के लिए एक नया मानक गुणवत्ता संचार ” , 125 वें एईएस कन्वेंशन, सैन फ्रांसिस्को, सीए, यूएसए, पहले से ही 7503, अक्टूबर 2008 और एक अन्य कॉन्फ्रेंस पेपर जहां वे अपनी खिड़की के फूरियर ट्रांसफॉर्म के परिमाण भी दिखाते हैं: शनेल, एम।, एट अल। 2007. एन्हांस्ड MPEG-4 कम विलंब AAC - कम बिटरेट उच्च गुणवत्ता संचार। 122 वें एईएस कन्वेंशन में ।
चित्रा 1. छाया विश्लेषण-प्रसंस्करण-संश्लेषण में विषम खिड़कियों के उपयोग का चित्रण। विश्लेषण-विंडो (नीला) और संश्लेषण खिड़की (पीले नारंगी) का उत्पाद (काला धराशायी) पिछले फ्रेम (धराशायी) से खिड़की के साथ एकता के लिए बोता है। MDCT का उपयोग करते समय सही पुनर्निर्माण की गारंटी देने के लिए और बाधाओं की आवश्यकता होती है।
असतत फूरियर ट्रांसफॉर्म (DFT, FFT) का उपयोग MDCT के बजाय किया जा सकता है, लेकिन ऐसे संदर्भों में निरर्थक वर्णक्रमीय डेटा दिया जाएगा। DFT की तुलना में, MDCT वर्णक्रमीय डेटा का केवल आधा हिस्सा देता है, जबकि उपयुक्त विंडोज़ को चुने जाने पर भी पूर्ण पुनर्निर्माण को सक्षम करता है।
यहां डीएफटी का उपयोग करके मैप किए गए विश्लेषण-प्रसंस्करण-संश्लेषण के लिए उपयुक्त मेरी खुद की असममित खिड़की का डिज़ाइन (छवि 2) है, लेकिन एमडीसीटी नहीं है जिसके साथ यह सही पुनर्निर्माण नहीं देता है। विंडो कुछ संभावित उपयोगी समय-डोमेन गुणों को बनाए रखते हुए माध्य-वर्ग समय और फ़्रीक्वेंसी बैंडवाइड्स ( सीमित गॉसियन विंडो के समान ) के उत्पाद को कम करने की कोशिश करती है : "शून्य शून्य" पर शिखर जिसके साथ विश्लेषण और संश्लेषण होता है। विंडो एक दूसरे की दर्पण छवियां हैं, फ़ंक्शन और पहली व्युत्पन्न निरंतरता, शून्य-मतलब जब खिड़की फ़ंक्शन के वर्ग को एक असामान्य संभावना घनत्व फ़ंक्शन के रूप में व्याख्या की जाती है। विभेदक विकास का उपयोग करके खिड़की को अनुकूलित किया गया था ।
चित्रा 2. वाम: अपने समय उलट प्रतिपक्ष संश्लेषण खिड़की के साथ एक साथ अतिव्यापी विश्लेषण-प्रसंस्करण-पुनर्जन्म के लिए उपयुक्त एक विषम विश्लेषण खिड़की। दायां: कोसाइन विंडो, विषम खिड़की के समान विलंबता के साथ
चित्रा 3. कोसाइन विंडो (ब्लू) और फिगर के असममित खिड़की (ऑरेंज) के फूरियर रूपांतरण के 2. विषमतापूर्ण खिड़की बेहतर आवृत्ति चयनात्मकता को दर्शाती है।
यहाँ भूखंडों के लिए और विषम खिड़की के लिए ऑक्टेव स्रोत कोड है। प्लॉटिंग कोड विकिमीडिया कॉमन्स से आता है । लिनक्स पर मैं इंस्टॉल करने की अनुशंसा gnuplot
, epstool
, pstoedit
, transfig
पहली और librsvg2-bin
के लिए का उपयोग करके देखने display
।
pkg load signal
graphics_toolkit gnuplot
set (0, "defaultaxesfontname", "sans-serif")
set (0, "defaultaxesfontsize", 12)
set (0, "defaultaxeslinewidth", 1)
function plotWindow (w, wname, wfilename = "", wspecifier = "", wfilespecifier = "")
M = 32; % Fourier transform size as multiple of window length
Q = 512; % Number of samples in time domain plot
P = 40; % Maximum bin index drawn
dr = 130; % Maximum attenuation (dB) drawn in frequency domain plot
N = length(w);
B = N*sum(w.^2)/sum(w)^2 % noise bandwidth (bins)
k = [0 : 1/Q : 1];
w2 = interp1 ([0 : 1/(N-1) : 1], w, k);
if (M/N < Q)
Q = M/N;
endif
figure('position', [1 1 1200 600])
subplot(1,2,1)
area(k,w2,'FaceColor', [0 0.4 0.6], 'edgecolor', [0 0 0], 'linewidth', 1)
if (min(w) >= -0.01)
ylim([0 1.05])
set(gca,'YTick', [0 : 0.1 : 1])
else
ylim([-1 5])
set(gca,'YTick', [-1 : 1 : 5])
endif
ylabel('amplitude')
set(gca,'XTick', [0 : 1/8 : 1])
set(gca,'XTickLabel',[' 0'; ' '; ' '; ' '; ' '; ' '; ' '; ' '; 'N-1'])
grid('on')
set(gca,'gridlinestyle','-')
xlabel('samples')
if (strcmp (wspecifier, ""))
title(cstrcat(wname,' window'), 'interpreter', 'none')
else
title(cstrcat(wname,' window (', wspecifier, ')'), 'interpreter', 'none')
endif
set(gca,'Position',[0.094 0.17 0.38 0.71])
H = abs(fft([w zeros(1,(M-1)*N)]));
H = fftshift(H);
H = H/max(H);
H = 20*log10(H);
H = max(-dr,H);
k = ([1:M*N]-1-M*N/2)/M;
k2 = [-P : 1/M : P];
H2 = interp1 (k, H, k2);
subplot(1,2,2)
set(gca,'FontSize',28)
h = stem(k2,H2,'-');
set(h,'BaseValue',-dr)
xlim([-P P])
ylim([-dr 6])
set(gca,'YTick', [0 : -10 : -dr])
set(findobj('Type','line'),'Marker','none','Color',[0.8710 0.49 0])
grid('on')
set(findobj('Type','gridline'),'Color',[.871 .49 0])
set(gca,'gridlinestyle','-')
ylabel('decibels')
xlabel('bins')
title('Fourier transform')
set(gca,'Position',[0.595 0.17 0.385 0.71])
if (strcmp (wfilename, ""))
wfilename = wname;
endif
if (strcmp (wfilespecifier, ""))
wfilespecifier = wspecifier;
endif
if (strcmp (wfilespecifier, ""))
savetoname = cstrcat('Window function and frequency response - ', wfilename, '.svg');
else
savetoname = cstrcat('Window function and frequency response - ', wfilename, ' (', wfilespecifier, ').svg');
endif
print(savetoname, '-dsvg', '-S1200,600')
close
endfunction
N=2^17; % Window length, B is equal for Triangular and Bartlett from 2^17
k=0:N-1;
w = -cos(2*pi*k/(N-1));
w .*= w > 0;
plotWindow(w, "Cosine")
freqData = [0.66697133904805994131, -0.20556692772918355727, 0.49267389481655493588, -0.25062332863369246594, -0.42388422228212319087, 0.42317609537724842905, -0.03930334287740060856, -0.11936153294075849129, 0.30201210285940127687, -0.15541616804857899536, -0.16208119255594669039, 0.12843871362286504723, -0.04470810646117385351, -0.00521885027256757845, 0.07185811583185619522, -0.02835116723496184862, -0.01393644785822748498, 0.00780746224568363342, -0.00748496824751256583, 0.00119325723511989282, 0.00194602547595042175];
freqData(1) /= 2;
scale = freqData(1) + sum(freqData.*not(mod(1:length(freqData), 2)));
freqData /= scale;
w = freqData(1)*ones(1, N);
for bin = 1:(length(freqData)/2)
w += freqData(bin*2)*cos(2*pi*bin*((1:N)-1)/N);
w += freqData(bin*2+1)*sin(2*pi*bin*((1:N)-1)/N);
endfor
w(N/4+1:N/2+1) = 0;
w(N/8+2:N/4) = (1 - w(N/8:-1:2).*w(7*N/8+2:N))./w(7*N/8:-1:6*N/8+2);
w = shift(w, -N/2);
plotWindow(w, "Asymmetrical");
आप विंडो के केवल हर दूसरे नमूने का उपयोग करना चाह सकते हैं क्योंकि यह शुरू होता है और शून्य पर समाप्त होता है। निम्नलिखित C ++ कोड आपके लिए ऐसा करता है जिससे आपको विंडो के एक चौथाई हिस्से को छोड़कर कोई भी शून्य नमूना नहीं मिलता है जो हर जगह शून्य है। विश्लेषण विंडो के लिए यह पहली तिमाही है और संश्लेषण खिड़की के लिए यह अंतिम तिमाही है। विश्लेषण विंडो की दूसरी छमाही को उनके उत्पाद की गणना के लिए संश्लेषण खिड़की के पहले छमाही के साथ गठबंधन किया जाना चाहिए। कोड भी विंडो के माध्य (संभाव्यता घनत्व फ़ंक्शन के रूप में) का परीक्षण करता है, और ओवरलैप किए गए पुनर्निर्माण का सपाटता दिखाता है।
#include <stdio.h>
#include <math.h>
int main() {
const int windowSize = 400;
double *analysisWindow = new double[windowSize];
double *synthesisWindow = new double[windowSize];
for (int k = 0; k < windowSize/4; k++) {
analysisWindow[k] = 0;
}
for (int k = windowSize/4; k < windowSize*7/8; k++) {
double x = 2 * M_PI * ((k+0.5)/windowSize - 1.75);
analysisWindow[k] = 2.57392230162633461887-1.58661480271141974718*cos(x)+3.80257516644523141380*sin(x)
-1.93437090055110760822*cos(2*x)-3.27163999159752183488*sin(2*x)+3.26617449847621266201*cos(3*x)
-0.30335261753524439543*sin(3*x)-0.92126091064427817479*cos(4*x)+2.33100177294084742741*sin(4*x)
-1.19953922321306438725*cos(5*x)-1.25098147932225423062*sin(5*x)+0.99132076607048635886*cos(6*x)
-0.34506787787355830410*sin(6*x)-0.04028033685700077582*cos(7*x)+0.55461815542612269425*sin(7*x)
-0.21882110175036428856*cos(8*x)-0.10756484378756643594*sin(8*x)+0.06025986430527170007*cos(9*x)
-0.05777077835678736534*sin(9*x)+0.00920984524892982936*cos(10*x)+0.01501989089735343216*sin(10*x);
}
for (int k = 0; k < windowSize/8; k++) {
analysisWindow[windowSize-1-k] = (1 - analysisWindow[windowSize*3/4-1-k]*analysisWindow[windowSize*3/4+k])/analysisWindow[windowSize/2+k];
}
printf("Analysis window:\n");
for (int k = 0; k < windowSize; k++) {
printf("%d\t%.10f\n", k, analysisWindow[k]);
}
double accu, accu2;
for (int k = 0; k < windowSize; k++) {
accu += k*analysisWindow[k]*analysisWindow[k];
accu2 += analysisWindow[k]*analysisWindow[k];
}
for (int k = 0; k < windowSize; k++) {
synthesisWindow[k] = analysisWindow[windowSize-1-k];
}
printf("\nSynthesis window:\n");
for (int k = 0; k < windowSize; k++) {
printf("%d\t%.10f\n", k, synthesisWindow[k]);
}
printf("Mean of square of analysis window as probability density function:\n%f", accu/accu2);
printf("\nProduct of analysis and synthesis windows:\n");
for (int k = 0; k < windowSize/2; k++) {
printf("%d\t%.10f\n", k, analysisWindow[windowSize/2+k]*synthesisWindow[k]);
}
printf("\nSum of overlapping products of windows:\n");
for (int k = 0; k < windowSize/4; k++) {
printf("%d\t%.10f\n", k, analysisWindow[windowSize/2+k]*synthesisWindow[k]+analysisWindow[windowSize/2+k+windowSize/4]*synthesisWindow[k+windowSize/4]);
}
delete[] analysisWindow;
delete[] synthesisWindow;
}
और अनुकूलन लागत समारोह के लिए स्रोत कोड के साथ प्रयोग की जाने वाली चुंबन FFT और एक अनुकूलन पुस्तकालय :
class WinProblem : public Opti::Problem {
private:
int numParams;
double *min;
double *max;
kiss_fft_scalar *timeData;
kiss_fft_cpx *freqData;
int smallSize;
int bigSize;
kiss_fftr_cfg smallFFTR;
kiss_fftr_cfg smallIFFTR;
kiss_fftr_cfg bigFFTR;
kiss_fftr_cfg bigIFFTR;
public:
// numParams must be odd
WinProblem(int numParams, int smallSize, int bigSize, double* candidate = NULL) : numParams(numParams), smallSize(smallSize), bigSize(bigSize) {
min = new double[numParams];
max = new double[numParams];
if (candidate != NULL) {
for (int i = 0; i < numParams; i++) {
min[i] = candidate[i]-fabs(candidate[i])*(1.0/65536);
max[i] = candidate[i]+fabs(candidate[i])*(1.0/65536);
}
} else {
for (int i = 0; i < numParams; i++) {
min[i] = -1;
max[i] = 1;
}
}
timeData = new kiss_fft_scalar[bigSize];
freqData = new kiss_fft_cpx[bigSize/2+1];
smallFFTR = kiss_fftr_alloc(smallSize, 0, NULL, NULL);
smallIFFTR = kiss_fftr_alloc(smallSize, 1, NULL, NULL);
bigFFTR = kiss_fftr_alloc(bigSize, 0, NULL, NULL);
bigIFFTR = kiss_fftr_alloc(bigSize, 1, NULL, NULL);
}
double *getMin() {
return min;
}
double *getMax() {
return max;
}
// ___ __ 1
// | \ | | | | | | | / |
// | \ | | | | | | | / |
// | \_ | | | | | | | / |
// | \|__ | | | | | | /| |
// | | -----|_______|___ | | | | / | |
// | | | | ----| | | |/ | |
// --------------------------------x-----------------------x---|---- 0
// 0 1/8 2/8 3/8 4/8 5/8 6/8 7/8 15/16
// |-------------------------------| |-------|
// zeroStarts winStarts
//
// f(x) = 0 if 4/8 < x < 7/8
// f(-x)f(x) + f(-x+1/8)f(x-1/8) = 1 if 0 < x < 1/8
double costFunction(double *params, double compare, int print) {
double penalty = 0;
double accu = params[0]/2;
for (int i = 1; i < numParams; i += 2) {
accu += params[i];
}
if (print) {
printf("%.20f", params[0]/2/accu);
for (int i = 1; i < numParams; i += 2) {
printf("+%.20fcos(%d pi x)", params[i]/accu, (i+1)/2);
printf("+%.20fsin(%d pi x)", params[i+1]/accu, (i+1)/2);
}
printf("\n");
}
if (accu != 0) {
for (int i = 0; i < numParams; i++) {
params[i] /= accu;
}
}
const int zeroStarts = 4; // Normally 4
const int winStarts = 2; // Normally 1
int i = 0;
int j = 0;
freqData[j].r = params[i++];
freqData[j++].i = 0;
for (; i < numParams;) {
freqData[j].r = params[i++];
freqData[j++].i = params[i++];
}
for (; j <= smallSize/2;) {
freqData[j].r = 0;
freqData[j++].i = 0;
}
kiss_fftri(smallIFFTR, freqData, timeData);
double scale = 1.0/timeData[0];
double tilt = 0;
double tilt2 = 0;
for (int i = 2; i < numParams; i += 2) {
if ((i/2)%2) {
tilt2 += (i/2)*params[i]*scale;
} else {
tilt2 -= (i/2)*params[i]*scale;
}
tilt += (i/2)*params[i]*scale;
}
penalty += fabs(tilt);
penalty += fabs(tilt2);
double accu2 = 0;
for (int i = 0; i < smallSize; i++) {
timeData[i] *= scale;
}
penalty += fabs(timeData[zeroStarts*smallSize/8]);
penalty += fabs(timeData[winStarts*smallSize/16]*timeData[smallSize-winStarts*smallSize/16]-0.5);
for (int i = 1; i < winStarts*smallSize/16; i++) {
// Last 16th
timeData[bigSize-winStarts*smallSize/16+i] = timeData[smallSize-winStarts*smallSize/16+i];
accu2 += timeData[bigSize-winStarts*smallSize/16+i]*timeData[bigSize-winStarts*smallSize/16+i];
}
// f(-1/8+i)*f(1/8-i) + f(i)*f(-i) = 1
// => f(-1/8+i) = (1 - f(i)*f(-i))/f(1/8-i)
// => f(-1/16) = (1 - f(1/16)*f(-1/16))/f(1/16)
// = 1/(2 f(1/16))
for (int i = 1; i < winStarts*smallSize/16; i++) {
// 2nd last 16th
timeData[bigSize-winStarts*smallSize/8+i] = (1 - timeData[i]*timeData[bigSize-i])/timeData[winStarts*smallSize/8-i];
accu2 += timeData[bigSize-winStarts*smallSize/8+i]*timeData[bigSize-winStarts*smallSize/8+i];
}
// Between 2nd last and last 16th
timeData[bigSize-winStarts*smallSize/16] = 1/(2*timeData[winStarts*smallSize/16]);
accu2 += timeData[bigSize-winStarts*smallSize/16]*timeData[bigSize-winStarts*smallSize/16];
for (int i = zeroStarts*smallSize/8; i <= bigSize-winStarts*smallSize/8; i++) {
timeData[i] = 0;
}
for (int i = 0; i < zeroStarts*smallSize/8; i++) {
accu2 += timeData[i]*timeData[i];
}
if (print > 1) {
printf("\n");
for (int x = 0; x < bigSize; x++) {
printf("%d,%f\n", x, timeData[x]);
}
}
scale = 1/sqrt(accu2);
if (print) {
printf("sqrt(accu2) = %f\n", sqrt(accu2));
}
double tSpread = 0;
timeData[0] *= scale;
double tMean = 0;
for (int i = 1; i <= zeroStarts*smallSize/8; i++) {
timeData[i] *= scale;
// tSpread += ((double)i)*((double)i)*(timeData[i]*timeData[i]);
double x_0 = timeData[i-1]*timeData[i-1];
double x_1 = timeData[i]*timeData[i];
tSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
double slope = timeData[i]-timeData[i-1];
if (slope > 0) {
penalty += slope+1;
}
tMean += x_1*i;
if (timeData[i] < 0) {
penalty -= timeData[i];
}
}
double x_0 = timeData[0]*timeData[0];
for (int i = 1; i <= winStarts*smallSize/8; i++) {
timeData[bigSize-i] *= scale;
double x_1 = timeData[bigSize-i]*timeData[bigSize-i];
tSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
x_0 = x_1;
tMean += x_1*(-i);
}
tMean /= smallSize;
penalty += fabs(tMean);
if (tMean > 0) {
penalty += 1;
}
tSpread /= ((double)smallSize)*((double)smallSize);
if (print) {
printf("tSpread = %f\n", tSpread);
}
kiss_fftr(bigFFTR, timeData, freqData);
double fSpread = 0;
x_0 = freqData[0].r*freqData[0].r;
for (int i = 1; i <= bigSize/2; i++) {
double x_1 = freqData[i].r*freqData[i].r+freqData[i].i*freqData[i].i;
fSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
x_0 = x_1;
}
if (print > 1) {
for (int i = 0; i <= bigSize/2; i++) {
printf("%d,%f,%f\n", i, freqData[i].r, freqData[i].i);
}
}
fSpread /= bigSize; // Includes kiss_fft scaling
if (print) {
printf("fSpread = %f\n", fSpread);
printf("%f,%f,%f\n", tSpread, fSpread, tSpread*fSpread);
}
return tSpread*fSpread + penalty;
}
double costFunction(double *params, double compare) {
return costFunction(params, compare, false);
}
int getNumDimensions() {
return numParams;
}
~WinProblem() {
delete[] min;
delete[] max;
delete[] timeData;
delete[] freqData;
KISS_FFT_FREE(smallFFTR);
KISS_FFT_FREE(smallIFFTR);
KISS_FFT_FREE(bigFFTR);
KISS_FFT_FREE(bigIFFTR);
}
};