package org.farng.mp3.id3; import java.io.IOException; import java.io.RandomAccessFile; import org.farng.mp3.InvalidTagException; import org.farng.mp3.object.AbstractMP3Object; import org.farng.mp3.object.ObjectGroupRepeated; import org.farng.mp3.object.ObjectNumberFixedLength; import org.farng.mp3.object.ObjectNumberHashMap; /** * <h3>4.5.   Event timing codes</h3> * <p/> * <p>   This frame allows synchronisation with key events in the audio. The<br>    header is:</p> * <p/> * <p>     <Header for 'Event timing codes', ID: "ETCO"><br> * <p/> *      Time stamp format    $xx</p> * <p/> * <p>   Where time stamp format is:</p> * <p/> * <p>     $01  Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit<br> *      $02  Absolute time, 32 bit sized, using milliseconds as unit</p> * <p/> * <p>   Absolute time means that every stamp contains the time from the<br>    beginning of the * file.</p> * <p/> * <p>   Followed by a list of key events in the following format:</p> * <p/> * <p>     Type of event   $xx<br> * <p/> *      Time stamp      $xx (xx ...)</p> * <p/> * <p>   The 'Time stamp' is set to zero if directly at the beginning of the<br>    sound or after * the previous event. All events MUST be sorted in<br>    chronological order. The type of event is as * follows:</p> * <p/> * <p>     $00  padding (has no meaning)<br>      $01  end of initial * silence<br>      $02  intro start<br> * <p/> *      $03  main part start<br>      $04  outro start<br> *      $05  outro end<br> * <p/> *      $06  verse start<br>      $07  refrain start<br> *      $08  interlude start<br> * <p/> *      $09  theme start<br>      $0A  variation start<br> *      $0B  key change<br> * <p/> *      $0C  time change<br>      $0D  momentary unwanted noise (Snap, * Crackle & Pop)<br>      $0E  sustained noise<br> * <p/> *      $0F  sustained noise end<br>      $10  intro end<br> *      $11  main part end<br> * <p/> *      $12  verse end<br>      $13  refrain end<br> *      $14  theme end<br> * <p/> *      $15  profanity<br>      $16  profanity end</p> * <p/> * <p>     $17-$DF  reserved for future use</p> * <p/> * <p>     $E0-$EF  not predefined synch 0-F</p> * <p/> * <p>     $F0-$FC  reserved for future use</p> * <p/> * <p>     $FD  audio end (start of silence)<br> * <p/> *      $FE  audio file ends<br>      $FF  one more byte of events * follows (all the following bytes with<br>           the value $FF have * the same function)</p> * <p/> * <p>   Terminating the start events such as "intro start" is OPTIONAL. The<br>    'Not * predefined synch's ($E0-EF) are for user events. You might want<br>    to synchronise your music to * something, like setting off an explosion<br>    on-stage, activating a screensaver etc.</p> * <p/> * <p>   There may only be one "ETCO" frame in each tag.<br> </p> * * @author Eric Farng * @version $Revision: 2374 $ */ public class FrameBodyETCO extends AbstractID3v2FrameBody { /** * Creates a new FrameBodyETCO object. */ public FrameBodyETCO() { super(); } /** * Creates a new FrameBodyETCO object. */ public FrameBodyETCO(final FrameBodyETCO body) { super(body); } /** * Creates a new FrameBodyETCO object. */ public FrameBodyETCO(final byte timeStampFormat, final byte event, final int timeStamp) { setObject("Time Stamp Format", new Long(timeStampFormat)); this.addGroup(event, timeStamp); } /** * Creates a new FrameBodyETCO object. */ public FrameBodyETCO(final RandomAccessFile file) throws IOException, InvalidTagException { this.read(file); } public String getIdentifier() { return "ETCO" + ((char) 0) + getOwner(); } public String getOwner() { return (String) getObject("Owner"); } public void getOwner(final String description) { setObject("Owner", description); } public void addGroup(final byte event, final int timeStamp) { final ObjectGroupRepeated group = (ObjectGroupRepeated) this.getObject("Data"); final AbstractMP3Object ev = new ObjectNumberHashMap("Type Of Event", 1); final AbstractMP3Object ts = new ObjectNumberFixedLength("Time Stamp", 4); group.addObject(ev); group.addObject(ts); setObject("Data", group); } protected void setupObjectList() { appendToObjectList(new ObjectNumberHashMap("Time Stamp Format", 1)); final ObjectGroupRepeated group = new ObjectGroupRepeated("Data"); group.addProperty(new ObjectNumberHashMap("Type Of Event", 1)); group.addProperty(new ObjectNumberFixedLength("Time Stamp", 4)); appendToObjectList(group); } }