EMMA Coverage Report (generated Tue Mar 14 21:50:42 EST 2006)
[all classes][org.farng.mp3.id3]

COVERAGE SUMMARY FOR SOURCE FILE [FrameBodySYLT.java]

nameclass, %method, %block, %line, %
FrameBodySYLT.java100% (1/1)45%  (10/22)35%  (233/659)38%  (48.9/127)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class FrameBodySYLT100% (1/1)45%  (10/22)35%  (233/659)38%  (48.9/127)
FrameBodySYLT (RandomAccessFile): void 0%   (0/1)0%   (0/26)0%   (0/9)
equals (): void 0%   (0/1)0%   (0/5)0%   (0/1)
getContentType (): byte 0%   (0/1)0%   (0/3)0%   (0/1)
getDescription (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getLanguage (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getSize (): int 0%   (0/1)0%   (0/26)0%   (0/4)
getTextEncoding (): byte 0%   (0/1)0%   (0/3)0%   (0/1)
read (RandomAccessFile): void 0%   (0/1)0%   (0/77)0%   (0/17)
readByteArray (byte []): void 0%   (0/1)0%   (0/44)0%   (0/10)
toString (): String 0%   (0/1)0%   (0/57)0%   (0/4)
write (RandomAccessFile): void 0%   (0/1)0%   (0/104)0%   (0/17)
writeByteArray (): byte [] 0%   (0/1)0%   (0/61)0%   (0/13)
addLyric (ObjectLyrics3Line): void 100% (1/1)77%  (46/60)75%  (12/16)
FrameBodySYLT (): void 100% (1/1)100% (23/23)100% (8/8)
FrameBodySYLT (FrameBodySYLT): void 100% (1/1)100% (73/73)100% (16/16)
FrameBodySYLT (byte, String, byte, byte, String): void 100% (1/1)100% (38/38)100% (13/13)
addLyric (int, String): void 100% (1/1)100% (18/18)100% (5/5)
getIdentifier (): String 100% (1/1)100% (2/2)100% (1/1)
getLyric (): String 100% (1/1)100% (25/25)100% (4/4)
getTimeStampFormat (): byte 100% (1/1)100% (3/3)100% (1/1)
iterator (): Iterator 100% (1/1)100% (4/4)100% (1/1)
setupObjectList (): void 100% (1/1)100% (1/1)100% (1/1)

1package org.farng.mp3.id3;
2 
3import org.farng.mp3.InvalidTagException;
4import org.farng.mp3.TagUtility;
5import org.farng.mp3.object.ObjectID3v2LyricLine;
6import org.farng.mp3.object.ObjectLyrics3Line;
7import org.farng.mp3.object.ObjectLyrics3TimeStamp;
8 
9import java.io.IOException;
10import java.io.RandomAccessFile;
11import java.util.Iterator;
12import java.util.LinkedList;
13 
14/**
15 * <h3>4.9.&nbsp;&nbsp; Synchronised lyrics/text</h3>
16 * <p/>
17 * <p>&nbsp;&nbsp; This is another way of incorporating the words, said or sung lyrics,<br> &nbsp;&nbsp; in the audio
18 * file as text, this time, however, in sync with the<br> &nbsp;&nbsp; audio. It might also be used to describing events
19 * e.g. occurring on a<br>
20 * <p/>
21 * &nbsp;&nbsp; stage or on the screen in sync with the audio. The header includes a<br> &nbsp;&nbsp; content
22 * descriptor, represented with as terminated text string. If no<br> &nbsp;&nbsp; descriptor is entered, 'Content
23 * descriptor' is $00 (00) only.</p>
24 * <p/>
25 * <p>&nbsp;&nbsp;&nbsp;&nbsp; &lt;Header for 'Synchronised lyrics/text', ID: &quot;SYLT&quot;&gt;<br>
26 * <p/>
27 * &nbsp;&nbsp;&nbsp;&nbsp; Text encoding&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $xx<br> &nbsp;&nbsp;&nbsp;&nbsp;
28 * Language&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $xx xx xx<br>
29 * &nbsp;&nbsp;&nbsp;&nbsp; Time stamp format&nbsp;&nbsp;&nbsp; $xx<br>
30 * <p/>
31 * &nbsp;&nbsp;&nbsp;&nbsp; Content type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $xx<br>
32 * &nbsp;&nbsp;&nbsp;&nbsp; Content descriptor&nbsp;&nbsp; &lt;text string according to encoding&gt; $00 (00)</p>
33 * <p/>
34 * <p>&nbsp;&nbsp; Content type:&nbsp;&nbsp; $00 is other<br>
35 * <p/>
36 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $01 is
37 * lyrics<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
38 * $02 is text transcription<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
39 * $03 is movement/part name (e.g. &quot;Adagio&quot;)<br>
40 * <p/>
41 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $04 is
42 * events (e.g. &quot;Don Quijote enters the stage&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
43 * $05 is chord (e.g. &quot;Bb F Fsus&quot;)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
44 * $06 is trivia/'pop up' information<br>
45 * <p/>
46 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $07 is
47 * URLs to webpages<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
48 * $08 is URLs to images</p>
49 * <p/>
50 * <p>&nbsp;&nbsp; Time stamp format:</p>
51 * <p/>
52 * <p>&nbsp;&nbsp;&nbsp;&nbsp; $01&nbsp; Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit<br>
53 * <p/>
54 * &nbsp;&nbsp;&nbsp;&nbsp; $02&nbsp; Absolute time, 32 bit sized, using milliseconds as unit</p>
55 * <p/>
56 * <p>&nbsp;&nbsp; Absolute time means that every stamp contains the time from the<br> &nbsp;&nbsp; beginning of the
57 * file.</p>
58 * <p/>
59 * <p>&nbsp;&nbsp; The text that follows the frame header differs from that of the<br>
60 * <p/>
61 * &nbsp;&nbsp; unsynchronised lyrics/text transcription in one major way. Each<br> &nbsp;&nbsp; syllable (or whatever
62 * size of text is considered to be convenient by<br> &nbsp;&nbsp; the encoder) is a null terminated string followed by
63 * a time stamp<br> &nbsp;&nbsp; denoting where in the sound file it belongs. Each sync thus has the<br> &nbsp;&nbsp;
64 * following structure:</p>
65 * <p/>
66 * <p>&nbsp;&nbsp;&nbsp;&nbsp; Terminated text to be synced (typically a syllable)<br> &nbsp;&nbsp;&nbsp;&nbsp; Sync
67 * identifier (terminator to above string)&nbsp;&nbsp; $00 (00)<br> &nbsp;&nbsp;&nbsp;&nbsp; Time
68 * stamp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
69 * $xx (xx ...)</p>
70 * <p/>
71 * <p>&nbsp;&nbsp; The 'time stamp' is set to zero or the whole sync is omitted if<br> &nbsp;&nbsp; located directly at
72 * the beginning of the sound. All time stamps<br> &nbsp;&nbsp; should be sorted in chronological order. The sync can be
73 * considered<br> &nbsp;&nbsp; as a validator of the subsequent string.</p>
74 * <p/>
75 * <p>&nbsp;&nbsp; Newline characters are allowed in all &quot;SYLT&quot; frames and MUST be used<br> &nbsp;&nbsp; after
76 * every entry (name, event etc.) in a frame with the content type<br> &nbsp;&nbsp; $03 - $04.</p>
77 * <p/>
78 * <p>&nbsp;&nbsp; A few considerations regarding whitespace characters: Whitespace<br>
79 * <p/>
80 * &nbsp;&nbsp; separating words should mark the beginning of a new word, thus<br> &nbsp;&nbsp; occurring in front of
81 * the first syllable of a new word. This is also<br> &nbsp;&nbsp; valid for new line characters. A syllable followed by
82 * a comma should<br> &nbsp;&nbsp; not be broken apart with a sync (both the syllable and the comma<br> &nbsp;&nbsp;
83 * should be before the sync).</p>
84 * <p/>
85 * <p>&nbsp;&nbsp; An example: The &quot;USLT&quot; passage</p>
86 * <p/>
87 * <p>&nbsp;&nbsp;&nbsp;&nbsp; &quot;Strangers in the night&quot; $0A &quot;Exchanging glances&quot;</p>
88 * <p/>
89 * <p>&nbsp;&nbsp; would be &quot;SYLT&quot; encoded as:</p>
90 * <p/>
91 * <p>&nbsp;&nbsp;&nbsp;&nbsp; &quot;Strang&quot; $00 xx xx &quot;ers&quot; $00 xx xx &quot; in&quot; $00 xx xx &quot;
92 * the&quot; $00 xx xx<br>
93 * <p/>
94 * &nbsp;&nbsp;&nbsp;&nbsp; &quot; night&quot; $00 xx xx 0A &quot;Ex&quot; $00 xx xx &quot;chang&quot; $00 xx xx
95 * &quot;ing&quot; $00 xx<br> &nbsp;&nbsp;&nbsp;&nbsp; xx &quot;glan&quot; $00 xx xx &quot;ces&quot; $00 xx xx</p>
96 * <p/>
97 * <p>&nbsp;&nbsp; There may be more than one &quot;SYLT&quot; frame in each tag, but only one<br> &nbsp;&nbsp; with the
98 * same language and content descriptor.<br> </p>
99 *
100 * @author Eric Farng
101 * @version $Revision: 1.5 $
102 */
103public class FrameBodySYLT extends AbstractID3v2FrameBody {
104 
105    LinkedList lines = new LinkedList();
106    String description = "";
107    String language = "";
108    byte contentType = 0;
109    byte textEncoding = 0;
110    byte timeStampFormat = 0;
111 
112    /**
113     * Creates a new FrameBodySYLT object.
114     */
115    public FrameBodySYLT() {
116        super();
117    }
118 
119    /**
120     * Creates a new FrameBodySYLT object.
121     */
122    public FrameBodySYLT(final FrameBodySYLT copyObject) {
123        super(copyObject);
124        this.description = new String(copyObject.description);
125        this.language = new String(copyObject.language);
126        this.contentType = copyObject.contentType;
127        this.textEncoding = copyObject.textEncoding;
128        this.timeStampFormat = copyObject.timeStampFormat;
129        ObjectID3v2LyricLine newLine;
130        for (int i = 0; i < copyObject.lines.size(); i++) {
131            newLine = new ObjectID3v2LyricLine((ObjectID3v2LyricLine) copyObject.lines.get(i));
132            this.lines.add(newLine);
133        }
134    }
135 
136    /**
137     * Creates a new FrameBodySYLT object.
138     */
139    public FrameBodySYLT(final byte textEncoding,
140                         final String language,
141                         final byte timeStampFormat,
142                         final byte contentType,
143                         final String description) {
144        this.textEncoding = textEncoding;
145        this.language = language;
146        this.timeStampFormat = timeStampFormat;
147        this.contentType = contentType;
148        this.description = description;
149    }
150 
151    /**
152     * Creates a new FrameBodySYLT object.
153     */
154    public FrameBodySYLT(final RandomAccessFile file) throws IOException, InvalidTagException {
155        this.read(file);
156    }
157 
158    public byte getContentType() {
159        return this.contentType;
160    }
161 
162    public String getDescription() {
163        return this.description;
164    }
165 
166    public String getIdentifier() {
167        return "SYLT";
168    }
169 
170    public String getLanguage() {
171        return this.language;
172    }
173 
174    public String getLyric() {
175        String lyrics = "";
176        for (int i = 0; i < this.lines.size(); i++) {
177            lyrics += this.lines.get(i);
178        }
179        return lyrics;
180    }
181 
182    public int getSize() {
183        int size;
184        size = 1 + 3 + 1 + 1 + this.description.length();
185        for (int i = 0; i < this.lines.size(); i++) {
186            size += ((ObjectID3v2LyricLine) this.lines.get(i)).getSize();
187        }
188        return size;
189    }
190 
191    public byte getTextEncoding() {
192        return this.textEncoding;
193    }
194 
195    public byte getTimeStampFormat() {
196        return this.timeStampFormat;
197    }
198 
199    public void addLyric(final int timeStamp, final String text) {
200        final ObjectID3v2LyricLine line = new ObjectID3v2LyricLine("Lyric Line");
201        line.setTimeStamp(timeStamp);
202        line.setText(text);
203        this.lines.add(line);
204    }
205 
206    public void addLyric(final ObjectLyrics3Line line) {
207        final Iterator iterator = line.getTimeStamp();
208        ObjectLyrics3TimeStamp timeStamp;
209        final String lyric = line.getLyric();
210        long time;
211        final ObjectID3v2LyricLine id3Line;
212        id3Line = new ObjectID3v2LyricLine("Lyric Line");
213        if (iterator.hasNext() == false) {
214            // no time stamp, give it 0
215            time = 0;
216            id3Line.setTimeStamp(time);
217            id3Line.setText(lyric);
218            this.lines.add(id3Line);
219        } else {
220            while (iterator.hasNext()) {
221                timeStamp = (ObjectLyrics3TimeStamp) iterator.next();
222                time = (timeStamp.getMinute() * 60) + timeStamp.getSecond(); // seconds
223                time *= 1000; // milliseconds
224                id3Line.setTimeStamp(time);
225                id3Line.setText(lyric);
226                this.lines.add(id3Line);
227            }
228        }
229    }
230 
231    /**
232     * This method is not yet supported.
233     *
234     * @throws java.lang.UnsupportedOperationException
235     *          This method is not yet supported
236     */
237    public void equals() {
238        // todo Implement this java.lang.Object method
239        throw new java.lang.UnsupportedOperationException("Method equals() not yet implemented.");
240    }
241 
242    public Iterator iterator() {
243        return this.lines.iterator();
244    }
245 
246    protected void setupObjectList() {
247//        throw new UnsupportedOperationException();
248    }
249 
250    public void read(final RandomAccessFile file) throws IOException, InvalidTagException {
251        final int size;
252        final int delim;
253        int offset = 0;
254        final byte[] buffer;
255        final String str;
256        size = readHeader(file);
257        buffer = new byte[size];
258        file.read(buffer);
259        str = new String(buffer);
260        this.textEncoding = buffer[offset++];
261        this.language = str.substring(offset, offset + 3);
262        offset += 3;
263        this.timeStampFormat = buffer[offset++];
264        this.contentType = buffer[offset++];
265        delim = str.indexOf(0, offset);
266        this.description = str.substring(offset, delim);
267        offset = delim + 1;
268        final byte[] data = new byte[size - offset];
269        System.arraycopy(buffer, offset, data, 0, size - offset);
270        readByteArray(data);
271    }
272 
273    public void readByteArray(final byte[] arr) {
274        int offset = 0;
275        int delim;
276        byte[] line;
277        for (int i = 0; i < arr.length; i++) {
278            if (arr[i] == 0) {
279                delim = i;
280                line = new byte[offset - delim + 4];
281                System.arraycopy(arr, offset, line, 0, offset - delim + 4);
282                this.lines.add(new ObjectID3v2LyricLine("Lyric Line"));
283                i += 4;
284                offset += 4;
285            }
286        }
287    }
288 
289    public String toString() {
290        String str;
291        str = getIdentifier() + " " + this
292                .textEncoding + " " + this
293                .language + " " + this
294                .timeStampFormat + " " + this
295                .contentType + " " + this
296                .description;
297        for (int i = 0; i < this.lines.size(); i++) {
298            str += (this.lines.get(i)).toString();
299        }
300        return str;
301    }
302 
303    public void write(final RandomAccessFile file) throws IOException {
304        final byte[] buffer;
305        int offset = 0;
306        writeHeader(file, this.getSize());
307        buffer = new byte[this.getSize()];
308        buffer[offset++] = this.textEncoding; // text encoding;
309        this.language = TagUtility.truncate(this.language, 3);
310        for (int i = 0; i < this.language.length(); i++) {
311            buffer[i + offset] = (byte) this.language.charAt(i);
312        }
313        offset += this.language.length();
314        buffer[offset++] = this.timeStampFormat;
315        buffer[offset++] = this.contentType;
316        for (int i = 0; i < this.description.length(); i++) {
317            buffer[i + offset] = (byte) this.description.charAt(i);
318        }
319        offset += this.description.length();
320        buffer[offset++] = 0; // null character
321        System.arraycopy(writeByteArray(), 0, buffer, offset, buffer.length - offset);
322        file.write(buffer);
323    }
324 
325    public byte[] writeByteArray() {
326        final byte[] arr;
327        ObjectID3v2LyricLine line = null;
328        int offset = 0;
329        int size = 0;
330        for (int i = 0; i < this.lines.size(); i++) {
331            line = (ObjectID3v2LyricLine) this.lines.get(i);
332            size += line.getSize();
333        }
334        arr = new byte[size];
335        for (int i = 0; i < this.lines.size(); i++) {
336            line = (ObjectID3v2LyricLine) this.lines.get(i);
337        }
338        if (line != null) {
339            System.arraycopy(line.writeByteArray(), 0, arr, offset, line.getSize());
340            offset += line.getSize();
341        }
342        return arr;
343    }
344}

[all classes][org.farng.mp3.id3]
EMMA 2.0.5312 (C) Vladimir Roubtsov