📄 248-253.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 Processing</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=5//-->
<!--PAGES=248-253//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="243-248.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="253-254.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H4 ALIGN="LEFT"><A NAME="Heading38"></A><FONT COLOR="#000077">Class Usage</FONT></H4>
<P>Because <I>OscopeFrame</I> implements the <I>DoubleDataProducer</I> interface, the subclass must implement the <I>getDoubleData</I> and <I>OpenDataFile</I> methods. The <I>AudioFrame</I> subclasses the <I>OscopeFrame</I>, as shown in the following code:</P>
<!-- CODE //-->
<PRE>
package lyon.audio;
import java.awt.*;
import gui.*;
import grapher.*;
import observers.*;
import futils.utils.*;
import futils.bench.*;
import futils.Futil;
import lyon.dclap.PictFrame;
public class AudioFrame extends OscopeFrame {
UlawCodec ulc;
...
</PRE>
<!-- END CODE //-->
<P>The <I>AudioFrame</I> constructor shows the name of the frame being passed to <I>OscopeFrame</I>:</P>
<!-- CODE SNIP //-->
<PRE>
public AudioFrame(String name) {
super(name);
....
</PRE>
<!-- END CODE SNIP //-->
<P>The <I>getDoubleData</I> and <I>OpenDataFile</I> methods are defined to keep the <I>AudioFrame</I> class from being abstract:</P>
<!-- CODE SNIP //-->
<PRE>
public double [] getDoubleData() {
return ulc.getDoubleArray();
}
public void openDataFile() {
ulc = new UlawCodec();
setDoubleData(ulc.getDoubleArray());
ulc.playAsync();
}
</PRE>
<!-- END CODE SNIP //-->
<P>Although no paint method was defined in <I>AudioFrame</I>, there were events. Thus, at the end of the event handler we are careful to call <I>super.handleEvent</I> so that the <I>OscopeFrame</I> events are processed:</P>
<!-- CODE SNIP //-->
<PRE>
public boolean handleEvent(Event e) {
if (Evt.match(e,saveSound_mi)) {
saveAs();
return true;
}....
return super.handleEvent(e);
}
</PRE>
<!-- END CODE SNIP //-->
<H4 ALIGN="LEFT"><A NAME="Heading39"></A><FONT COLOR="#000077">Modifying OscopeFrame</FONT></H4>
<P>Once a user starts to use the <I>OscopeFrame</I> class, there may be a need to add features without altering the existing API. One approach is to add to the existing menu bar. In the following code, we demonstrate how to add the capability to turn the <I>OscopeFrame</I> grid on and off using a menu item in the main menu bar. <I>OscopeFrame</I> extends <I>PictFrame</I>, and, inheriting an existing menu bar. To add an item to the menu bar, we add the following instance variables to the <I>OscopeFrame</I> class:</P>
<!-- CODE SNIP //-->
<PRE>
private boolean drawGrid = true;
private MenuBar mb = getMenuBar();
private Menu m = new Menu("Scope Menu");
private MenuItem drawGrid_mi =
new MenuItem("[d]raw grid");
</PRE>
<!-- END CODE SNIP //-->
<P>When the user presses <B>d</B> or selects the <B>[d]raw grid</B> item from the main menu bar, we want to turn off the drawing of the grid. The first step is to modify the <I>handleEvent</I> method:</P>
<!-- CODE SNIP //-->
<PRE>
public boolean handleEvent(Event e) {
if(Evt.match(e,drawGrid_mi)) {
drawGrid = ! drawGrid;
return true;
}....
</PRE>
<!-- END CODE SNIP //-->
<P>Second, we modify is in the <I>drawTrace</I> method:</P>
<!-- CODE //-->
<PRE>
private void drawTrace(Graphics g) {
doubleData = getDoubleData();
double limit = (double)(doubleData.length * xScaleFactor);
dim = size();
height = dim.height;
width = dim.width;
</PRE>
<!-- END CODE //-->
<P>In the following line, we check the status of the <I>drawGrid</I> variable to see whether a grid should be drawn.</P>
<!-- CODE SNIP //-->
<PRE>
if (drawGrid)
Draw.grid(20, g, gridColor);
....
</PRE>
<!-- END CODE SNIP //-->
<H4 ALIGN="LEFT"><A NAME="Heading40"></A><FONT COLOR="#000077">Switching the Scaling Labels</FONT></H4>
<P>A unique feature of <I>OscopeFrame</I> is that it automatically switches to a next logical range when the user clicks in the time-scale or voltage-scale scroll bar. This interface hack is clever enough to warrant some explanation.</P>
<P><I>OscopeFrame</I> has a series of predefined scale factors, with corresponding labels, for time scaling (y-scale) and voltage scaling (x-scale). They are held as private class variables:</P>
<!-- CODE //-->
<PRE>
1. private final double
2. xScaleFactors[] = {50000, 25000, 10000, 5000, 2500, 1000,
3. 250, 100, 50, 25, 10,
4. 2.5, 1, .5, .25, .1,
5. .025, .01, .005, .0025, .001,
6.;
7. private final String xSFLabels[] = {"0.05 u", "0.1 u", "0.25 u",
8. "0.5 u", "1 u", "2.5 u",
9. "5 u", "10 u", "25 u",
10. "50 u", "100 u", "250 u",
11. "500 u", "1 m", "2.5 m",
12. "5 m", "10 m", "25 m",
13. "50 m", "100 m", "250 m",
14. "500 m", "1 ", "2.5 ",
15. "5 "};
</PRE>
<!-- END CODE //-->
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR><B>NOTE: </B><I>xsfStartIndex</I> indicates the default start point for the scale factor and its label. This has a direct correspondence with the y-scale factors, shown in line 32.<HR></FONT>
</BLOCKQUOTE>
<!-- CODE //-->
<PRE>
16. private final int xsfStartIndex = 14;
17. private double xScaleFactor = xScaleFactors[xsfStartIndex];
18. private double oldXScaleFactor = xScaleFactors[xsfStartIndex];
19. private String xSFLabel = new String(xSFLabels[xsfStartIndex]);
20. private final double
21. yScaleFactors[] = {
22. 200, 100, 50, 20, 10,
23. 2, 1, .5, .2, .1};
24. private final String
25. ySFLabels[] = {
26. "1 m", "2.5 m",
27. "5 m", "10 m",
28. "25 m", "50 m",
29. "100 m", "250 m",
30. "500 m", "1 ",
31. "2.5 ", "5 "};
32. private final int ysfStartIndex = 8;
33. private double yScaleFactor = 1;
34. private double oldYScaleFactor = 1;
35. private String ySFLabel = new String(ySFLabels[ysfStartIndex]);
</PRE>
<!-- END CODE //-->
<P>The clever bit is that the top and bottom scroll bar instances return integers that can be used to index into the label and scale arrays. This technique is shown in the following code, which is excerpted from the <I>handleEvent</I> method:</P>
<!-- CODE //-->
<PRE>
if(e.target == sbHorzTop) {
int i = sbHorzTop.getValue();
xScaleFactor = xScaleFactors[i];
if (xScaleFactor != oldXScaleFactor) {
xSFLabel = xSFLabels[i];
repaint();
oldXScaleFactor = xScaleFactor;
}
return true;
}
</PRE>
<!-- END CODE //-->
<P>The scroll bar characteristics are set so that they will return only a valid range for an index into the scale factors and scale labels:
</P>
<!-- CODE SNIP //-->
<PRE>
// Set top scroll bar characteristics
sbHorzTop.setValues(xsfStartIndex, 0, 0, 24);
// Set right scroll bar characteristics
sbVertRight.setValues(ysfStartIndex, 0, 0, 11);
</PRE>
<!-- END CODE SNIP //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="243-248.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="253-254.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 + -