View Javadoc

1   package edu.iris.dmc.seedcodec;
2   
3   import java.io.*;
4   
5   /***
6    * This class acts as a container to hold encoded bytes processed
7    * by a Steim compression routine, as well as supporting information
8    * relating to the data processed.
9    * It also facilitates Steim notation and the formation
10   * of the data frames.
11   * This class stores the Steim encoding, but is ignorant of the encoding
12   * process itself...it's just for self-referencing.
13   * @author Robert Casey (IRIS DMC)
14   * @version 12/10/2001
15   */
16  
17  public class SteimFrameBlock {
18  
19  	// *** constructors *** 
20  
21  	/***
22  	 * Create a new block of Steim frames for a particular version of Steim
23  	 * copression.
24  	 * Instantiate object with the number of 64-byte frames
25  	 * that this block will contain (should connect to data
26  	 * record header such that a proper power of 2 boundary is
27  	 * formed for the data record) AND the version of Steim
28  	 * compression used (1 and 2 currently)
29  	 * the number of frames remains static...frames that are
30  	 * not filled with data are simply full of nulls.
31  	 * @param numFrames the number of frames in this Steim record
32  	 * @param steimVersion which version of Steim compression is being used
33  	 * (1,2,3).
34  	 */
35  	public SteimFrameBlock (int numFrames, int steimVersion) {
36  		steimFrame = new SteimFrame[numFrames]; // array of frames
37  		for (int i = 0; i < steimFrame.length; i++) {
38  			// initialize the SteimFrame array
39  			steimFrame[i] = new SteimFrame();
40  		}
41  		this.numFrames = numFrames;
42  		this.steimVersion = steimVersion;
43  
44  		// initialize the first frame properly
45  		currentFrame = 0;            // sanity
46  		addEncodingNibble(0); // first nibble always 00
47  		this.steimFrame[currentFrame].pos++;  // increment position in frame to W1
48  	}
49  
50  
51  	// *** public methods ***
52  
53  	/***
54  	 * Return the number of data samples represented by this frame block
55  	 * @return integer value indicating number of samples
56  	 */
57  	public int getNumSamples () {
58  		return numSamples;
59  	}
60  
61  	/***
62  	 * Return the version of Steim compression used
63  	 * @return integer value representing the Steim version (1,2,3)
64  	 */
65  	public int getSteimVersion () {
66  		return steimVersion;
67  	}
68  
69  	/***
70  	 * Return the compressed byte representation of the data for inclusion
71  	 * in a data record.
72  	 * @return byte array containing the encoded, compressed data
73  	 * @throws IOException from called method(s)
74  	 */
75  	public byte[] getEncodedData () throws IOException {
76  		// set up a byte array to write int words to
77  		ByteArrayOutputStream encodedData = 
78  			new ByteArrayOutputStream(numFrames * 64);
79  		// set up interface to the array for writing the ints
80  		DataOutputStream intSerializer = 
81  			new DataOutputStream(encodedData);
82  		for (int i = 0; i < numFrames; i++) {  // for each frame
83  			for (int j = 0; j < 16; j++) {     // for each word
84  				// write integer to byte stream
85  				intSerializer.writeInt(steimFrame[i].word[j]);	
86  			}
87  		}
88  
89  		return encodedData.toByteArray(); // return byte stream as array
90  	}
91  
92  	/***
93  	 * Return the number of frames in this frame block
94  	 * @return integer value indicating number of frames
95  	 */
96  	public int getNumFrames () {
97  		return numFrames;
98  	}
99  
100 
101 	// *** private and protected methods ***
102 
103 	/***
104 	 * Add a single 32-bit word to current frame.
105 	 * @param samples the number of sample differences in the word
106 	 * @param nibble a value of 0 to 3 that reflects the W0 encoding
107 	 * for this word
108 	 * @return boolean indicating true if the block is full (ie: the
109 	 * calling app should not add any more to this object)
110 	 */
111 	protected boolean addEncodedWord (int word, int samples, int nibble) {
112 		int pos = steimFrame[currentFrame].pos; // word position
113 		steimFrame[currentFrame].word[pos] = word; // add word
114 		addEncodingNibble (nibble);                     // add nibble
115 		numSamples += samples;
116 		pos++;     // increment position in frame
117 		if (pos > 15) {  // need next frame?
118 			currentFrame++;
119 			if (currentFrame >= numFrames) {  // exceeded frame limit?
120 				return true;  // block is full
121 			}
122 			addEncodingNibble(0); // first nibble always 00
123 		}
124 		steimFrame[currentFrame].pos++;  // increment position in frame
125 		return false;  // block is not yet full
126 	}
127 
128 	/***
129 	 * Set the reverse integration constant X(N) explicitly to the
130 	 * provided word value.
131 	 * This method is typically used to reset X(N) should the compressor
132 	 * fill the frame block before all samples have been read.
133 	 * @param word integer value to be placed in X(N)
134 	 */
135 	protected void setXsubN (int word) {
136 		steimFrame[0].word[2] = word;
137 		return;
138 	}
139 
140 	/***
141 	* Add encoding nibble to W0.
142 	* @param bitFlag a value 0 to 3 representing an encoding nibble
143 	*/
144 	private void addEncodingNibble (int bitFlag) {
145 		int offset = steimFrame[currentFrame].pos; // W0 nibble offset - determines Cn in W0
146 		int shift = (15 - offset)*2;  // how much to shift bitFlag
147 		steimFrame[currentFrame].word[0] |= (bitFlag << shift);
148 		return;
149 	}
150 
151 
152 	// *** inner classes ***
153 
154 	/***
155 	 * This represents a single Steim compression frame.  It stores values
156 	 * as an int array and keeps track of it's current position in the frame.
157 	 */
158 	private class SteimFrame {
159 		public int[] word = new int[16];  // 16 32-byte words
160 		public int pos = 0;  // word position in frame (pos: 0 = W0, 1 = W1, etc...)
161 	}
162 
163 
164 	// *** instance variables ***
165 
166 	private int numFrames = 0;        // number of frames this object contains
167 	private int numSamples = 0;      // number of samples represented
168 	private int steimVersion = 0;    // Steim version number
169 	private int currentFrame = 0;     // number of current frame being built
170 	private SteimFrame[] steimFrame = null;  // array of frames;
171 }