📄 282-286.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1558515682"><META name=vstitle content="Java Digital Signal Processing"><META name=vsauthor content="Douglas A. Lyon"><META name=vsimprint content="M&T Books"><META name=vspublisher content="IDG Books Worldwide, Inc."><META name=vspubdate content="11/01/97"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Java Digital Signal Processing:Digital Audio Transform Recipes</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<!--ISBN=1558515682//-->
<!--TITLE=Java Digital Signal Processing//-->
<!--AUTHOR=Douglas A. Lyon//-->
<!--PUBLISHER=IDG Books Worldwide, Inc.//-->
<!--IMPRINT=M & T Books//-->
<!--CHAPTER=6//-->
<!--PAGES=282-286//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="278-282.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="286-293.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P>Figure 6.5 shows the part of the Audio menu in the main menu bar in the <I>AudioFrame</I> that contains the transform fragments for performing the FFT manipulations. The keyboard shortcuts are shown in brackets.</P>
<P><A NAME="Fig5"></A><A HREF="javascript:displayWindow('images/06-05.jpg',158,80 )"><IMG SRC="images/06-05t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/06-05.jpg',158,80)"><FONT COLOR="#000077"><B>Figure 6.5</B></FONT></A> The transform fragment of the <I>AudioFrame</I>.
</P>
<P>The menu items are initialized at the head of the <I>AudioFrame</I> class using the following code fragment:</P>
<!-- CODE SNIP //-->
<PRE>
MenuItem fft_mi = addMenuItem(m,”[1] FFT”);
MenuItem ifft_mi = addMenuItem(m,”[2] IFFT”);
MenuItem dft_mi = addMenuItem(m,”[3] DFT”);
MenuItem idft_mi = addMenuItem(m,”[4] IDFT”);
MenuItem graphPSD_mi = addMenuItem(m,”[5] Graph PSD, R and I”);
</PRE>
<!-- END CODE SNIP //-->
<P>Events are handled in the <I>handleEvent</I> method, using the <I>Evt</I> class to detect the keyboard shortcuts. This technique enables rapid processing.</P>
<!-- CODE //-->
<PRE>
if (Evt.match(e,fft_mi)) {
fft();
return true;
}
if (Evt.match(e,ifft_mi)) {
ifft();
return true;
}
if (Evt.match(e, dft_mi)) {
fftInstance = dft();
return true;
}
if (Evt.match(e, idft_mi)) {
idft(fftInstance);
return true;
}
if (Evt.match(e, graphPSD_mi)) {
graphPSD();
return true;
}
</PRE>
<!-- END CODE //-->
<P>A class variable called <I>fftInstance</I> passes the complex data results from method to method. The <I>fftInstance</I> is declared after the <I>Oscillator</I> and <I>UlawCodec</I> instances.</P>
<!-- CODE SNIP //-->
<PRE>
public class AudioFrame extends OscopeFrame {
private Oscillator osc =
new Oscillator(400,4000);
UlawCodec ulc;
FFT fftInstance;
</PRE>
<!-- END CODE SNIP //-->
<P>The following DFT and IDFT code includes facilities for benchmarking the execution of the DFT on long sequences. We find the DFT and IDFT to be so slow that they are of interest only for timing purposes. As a twist on the implementation possibilities, we also show the <I>dft</I> method returning an instance of the <I>FFT</I> class, which is used to replace the <I>fftInstance</I> class variable in the <I>handleEvent</I> method.</P>
<!-- CODE //-->
<PRE>
public FFT dft() {
double doubleArray[] = ulc.getDoubleArray();
double [] psd;
FFT f = new FFT();
Timer t1 = new Timer();
t1.mark();
psd=f.dft( doubleArray);
// Stop the timer and report.
t1.record();
System.out.println(“Time to perform DFT:”);
t1.report();
f.graphs();
return f;
}
</PRE>
<!-- END CODE //-->
<P>The <I>handleEvent</I> method passes <I>fftInstance</I> to the <I>idft</I> method for processing. Thus, the <I>idft</I> method overwrites the <I>fftInstance</I> variable (it is passed, like all instances, by reference). The <I>idft</I> method follows:</P>
<!-- CODE //-->
<PRE>
public void idft(FFT f) {
double doubleArray[];
Timer t1 = new Timer();
t1.mark();
doubleArray=f.idft( );
// Stop the timer and report.
t1.record();
System.out.println(“Time to perform IDFT:”);
t1.report();
f.graphs();
}
</PRE>
<!-- END CODE //-->
<P>In the following <I>fft</I> method, <I>fftInstance</I> is overwritten. Data is obtained from the <I>getTruncatedDoubleData</I> method, which truncates the input data to the nearest integral power of two. We have elected to perform this truncation explicitly, because some users might prefer to pad their input data with extra samples. If the input data consisted of 2,049 samples, such a practice would pad the input data to 4,096 samples, doubling the processing time. The loss of data may be objectionable, so we have elected to perform the truncation, or padding, outside the <I>FFT</I> class.</P>
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR><B>WARNING: </B>Be careful—if the input to the FFT is not an integral power of two, the <I>forwardFFT</I> and <I>reverseFFT</I> methods will produce wrong results, because no check is performed.<HR></FONT>
</BLOCKQUOTE>
<!-- CODE SNIP //-->
<PRE>
public void fft() {
fftInstance = new FFT();
double[] r_d = getTruncatedDoubleData();
double[] i_d = new double[r_d.length];
fftInstance.forwardFFT(r_d, i_d);
ulc.play();
}
</PRE>
<!-- END CODE SNIP //-->
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR><B>NOTE: </B>The <I>UlawCodec</I> instance, <I>ulc</I>, is played after the <I>fft</I>.<HR></FONT>
</BLOCKQUOTE>
<P>The audio data <I>AudioFrame</I> class is not shortened or altered by the <I>fft</I> invocation. The play invocation simply signals when <I>fft</I> is complete.</P>
<P>The audio data is copied before truncation occurs. It is not overwritten until after the <I>ifft</I> method is invoked. The <I>getTruncatedDoubleData</I> truncation method follows:</P>
<!-- CODE //-->
<PRE>
double [] getTruncatedDoubleData() {
double[] temp = FFT.arrayCopy(getDoubleData());
int trunc = 1 << FFT.log2(temp.length);
System.out.println(“Truncated size: “ + trunc);
double[] truncArray = new double[trunc];
for (int i=0; i < trunc; i++)
truncArray[i] = temp[i];
return truncArray;
}
</PRE>
<!-- END CODE //-->
<P>Performing an FFT is sometimes called <I>analysis</I>. After the analysis, there may be a frequency-domain-based pattern recognition (what note was played) or a spectral modification (filtering, pitch-shifting, and so on). The IFFT is sometimes called <I>synthesis</I>, because the time-domain waveform is resynthesized from the frequency domain description. The implementation of the <I>ifft</I> method in the <I>AudioFrame</I> follows:</P>
<!-- CODE //-->
<PRE>
public void ifft() {
double realInput[] =
FFT.arrayCopy(fftInstance.getReal());
double imaginaryInput[] =
FFT.arrayCopy(fftInstance.getImaginary());
fftInstance.reverseFFT(realInput,imaginaryInput);
ulc = new UlawCodec(realInput);
ulc.play();
}
</PRE>
<!-- END CODE //-->
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR><B>NOTE: </B>The <I>ifft</I> method throws away the imaginary part of the <I>reverseFFT</I> method’s output. For real input signals, in theory the imaginary part is zero. We have found, however, that there is some small near-zero imaginary part. It has been attributed to round-off error.<HR></FONT>
</BLOCKQUOTE>
<P>The PSD is graphed using <I>graphPSD</I>:</P>
<!-- CODE SNIP //-->
<PRE>
public void graphPSD() {
Graph.graph(fftInstance.computePSD(),
“PSD of truncated waveform”,”a^2”);
};
</PRE>
<!-- END CODE SNIP //-->
<P>For example, suppose that a saw wave is used as an input. The saw wave and PSD are shown using the <I>OscopeFrame</I> and <I>graph</I> methods on the left and right in Figure 6.6.</P>
<P><A NAME="Fig6"></A><A HREF="javascript:displayWindow('images/06-06.jpg',413,220 )"><IMG SRC="images/06-06t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/06-06.jpg',413,220)"><FONT COLOR="#000077"><B>Figure 6.6</B></FONT></A> Saw wave and spectral output from the <I>graphPSD</I> method.
</P>
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR><B>NOTE: </B>Real signals always have a spectrum that is symmetric about its center.<HR></FONT>
</BLOCKQUOTE>
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="278-282.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="286-293.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<hr width="90%" size="1" noshade><div align="center"><font face="Verdana,sans-serif" size="1">Copyright © <a href="/reference/idgbooks00001.html">IDG Books Worldwide, Inc.</a></font></div>
<!-- all of the reference materials (books) have the footer and subfoot reveresed --><!-- reference_subfoot = footer --><!-- reference_footer = subfoot --></BODY></HTML><!-- END FOOTER -->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -