/*
* JSwiff is an open source Java API for Macromedia Flash file generation
* and manipulation
*
* Copyright (C) 2004-2005 Ralf Terdic (contact@jswiff.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.jswiff.swfrecords.tags;
import com.jswiff.io.InputBitStream;
import com.jswiff.io.OutputBitStream;
import java.io.IOException;
/**
* <p>
* This tag is used to define the format of streaming sound data (contained in
* <code>SoundStreamBlock</code> tags). It extends the
* <code>SoundStreamHead</code> tag in flexibility, supporting more encoding
* formats and sample sizes.
* </p>
*
* <p>
* Warning: you are responsible for obtaining technology licenses needed for
* encoding and decoding sound data (see e.g. <a
* href="http://mp3licensing.com">mp3licensing.com</a> for details on mp3
* licensing).
* </p>
*
* @see SoundStreamHead
* @see SoundStreamBlock
*/
public final class SoundStreamHead2 extends Tag {
/**
* Uncompressed sound format. For 16-bit samples, native byte ordering
* (little-endian or big-endian) is used. Warning: this introduces
* platform dependency!
*/
public static final byte FORMAT_UNCOMPRESSED = 0;
/**
* ADPCM compressed sound format (simple compression algorithm without
* licensing issues).
*/
public static final byte FORMAT_ADPCM = 1;
/**
* mp3 compressed sound format (for high-quality sound encoding) (since SWF
* 4).
*/
public static final byte FORMAT_MP3 = 2;
/**
* Uncompressed little-endian sound format, i.e. 16-bit samples are decoded
* using little-endian byte ordering (platform-independent format) (since
* SWF 4).
*/
public static final byte FORMAT_UNCOMPRESSED_LITTLE_ENDIAN = 3;
/**
* Nellymoser Asao compressed sound format (optimized for low-bitrate mono
* speech transmission) (since SWF 6).
*/
public static final byte FORMAT_NELLYMOSER = 6;
/** 5.5 kHz sampling rate */
public static final byte RATE_5500_HZ = 0;
/** 11 kHz sampling rate */
public static final byte RATE_11000_HZ = 1;
/** 22 kHz sampling rate */
public static final byte RATE_22000_HZ = 2;
/** 44 kHz sampling rate */
public static final byte RATE_44000_HZ = 3;
private byte playbackRate;
private boolean isPlayback16BitSample;
private boolean isPlaybackStereo;
private byte streamFormat;
private byte streamRate;
private boolean isStream16BitSample;
private boolean isStreamStereo;
private int streamSampleCount;
private short latencySeek;
/**
* <p>
* Creates a new SoundStreamHead2 tag. Supply the encoding format of the
* stream (one of the provided <code>FORMAT_...</code> constants), its
* sampling rate (use <code>RATE_...</code> constants), specify whether
* the sample size is 16 bit or 8 bit, and provide the channel count (mono
* / stereo) and the average number of samples (for stereo sound: sample
* pairs) per SoundStreamBlock.
* </p>
*
* <p>
* The advisory playback parameters (sampling rate, sample size and channel
* count) are set to be identical to the stream's parameters specified
* here. Use <code>setPlayback...()</code> methods for changing these
* values.
* </p>
*
* @param format encoding format (mp3 or ADPCM)
* @param rate sampling rate
* @param is16BitSample if <code>true</code>, sample size is 16 bit,
* otherwise 8 bit
* @param isStereo if <code>true</code>, sound is stereo, otherwise mono
* @param sampleCount average number of samples (stereo: sample pairs) per
* block
*/
public SoundStreamHead2(
byte format, byte rate, boolean is16BitSample, boolean isStereo,
int sampleCount) {
code = TagConstants.SOUND_STREAM_HEAD_2;
this.streamFormat = format;
this.streamRate = rate;
this.playbackRate = rate;
this.isStream16BitSample = is16BitSample;
this.isPlayback16BitSample = is16BitSample;
this.isStreamStereo = isStereo;
this.isPlaybackStereo = isStereo;
this.streamSampleCount = sampleCount;
}
SoundStreamHead2() {
// empty
}
/**
* Used only with mp3 streaming sounds; sets the number of mp3 samples to
* be skipped at the beginning of the sound stream (initial latency). This
* value must match the number of mp3 samples to be skipped (i.e. the
* SeekSamples value) from the first SoundStreamBlock.
*
* @param latencySeek initial latency of sound stream
*/
public void setLatencySeek(short latencySeek) {
this.latencySeek = latencySeek;
}
/**
* Used only with mp3 streaming sounds; returns the number of mp3 samples
* to be skipped at the beginning of the sound stream (initial latency).
*
* @return initial latency of sound stream
*/
public short getLatencySeek() {
return latencySeek;
}
/**
* Sets the sample size for playback (16 bit / 8 bit).
*
* @param is16BitSample <code>true</code> for 16 bit, <code>false</code>
* for 8 bit
*/
public void setPlayback16BitSample(boolean is16BitSample) {
this.isPlayback16BitSample = is16BitSample;
}
/**
* Checks the sample size for playback (16 bit / 8 bit).
*
* @return <code>true</code> for 16 bit, <code>false</code> for 8 bit
*/
public boolean isPlayback16BitSample() {
return isPlayback16BitSample;
}
/**
* Sets the playback sampling rate.
*
* @param rate advisory playback rate
*/
public void setPlaybackRate(byte rate) {
this.playbackRate = rate;
}
/**
* Returns the playback sampling rate.
*
* @return advisory playback rate
*/
public byte getPlaybackRate() {
return playbackRate;
}
/**
* Sets the number of channels used at playback (mono/stereo).
*
* @param isStereo <code>true</code> for stereo, <code>false</code> for
* mono
*/
public void setPlaybackStereo(boolean isStereo) {
this.isPlaybackStereo = isStereo;
}
/**
* Checks the number of channels used at playback (mono/stereo).
*
* @return <code>true</code> for stereo, <code>false for mono</code>
*/
public boolean isPlaybackStereo() {
return isPlaybackStereo;
}
/**
* Specifies the sound stream's sample size (16 bit / 8 bit).
*
* @param isStream16BitSample <code>true</code> for 16 bit,
* <code>false</code> for 8 bit
*/
public void setStream16BitSample(boolean isStream16BitSample) {
this.isStream16BitSample = isStream16BitSample;
}
/**
* Checks the sound stream's sample size (16 bit / 8 bit).
*
* @return <code>true</code> for 16 bit, <code>false</code> for 8 bit
*/
public boolean isStream16BitSample() {
return isStream16BitSample;
}
/**
* Specifies the encoding format of the sound stream (one of the
* <code>FORMAT_...</code> constants).
*
* @param streamFormat sound encoding format
*/
public void setStreamFormat(byte streamFormat) {
this.streamFormat = streamFormat;
}
/**
* Returns the encoding format of the sound stream (one of the
* <code>FORMAT_...</code> constants).
*
* @return sound encoding format
*/
public byte getStreamFormat() {
return streamFormat;
}
/**
* Specifies the sampling rate of the sound stream (one of the
* <code>RATE_...</code> constants).
*
* @param streamRate sampling rate
*/
public void setStreamRate(byte streamRate) {
this.streamRate = streamRate;
}
/**
* Returns the sampling rate of the sound stream (one of the
* <code>RATE_...</code> constants).
*
* @return sampling rate
*/
public byte getStreamRate() {
return streamRate;
}
/**
* Specifies the average number of samples (for stereo sound: sample pairs)
* per SoundStreamBlock.
*
* @param streamSampleCount average sample count per block
*/
public void setStreamSampleCount(int streamSampleCount) {
this.streamSampleCount = streamSampleCount;
}
/**
* Returns the average number of samples (for stereo sound: sample pairs)
* per SoundStreamBlock.
*
* @return average sample count per block
*/
public int getStreamSampleCount() {
return streamSampleCount;
}
/**
* Specifies whether the streaming sound is stereo or not.
*
* @param isStreamStereo <code>true</code> if stereo, otherwise
* <code>false</code>
*/
public void setStreamStereo(boolean isStreamStereo) {
this.isStreamStereo = isStreamStereo;
}
/**
* Checks whether the streaming sound is stereo or not.
*
* @return <code>true</code> if stereo, otherwise <code>false</code>
*/
public boolean isStreamStereo() {
return isStreamStereo;
}
protected void writeData(OutputBitStream outStream)
throws IOException {
outStream.writeUnsignedBits(0, 4); // 4 reserved bits
outStream.writeUnsignedBits(playbackRate, 2);
outStream.writeBooleanBit(isPlayback16BitSample);
outStream.writeBooleanBit(isPlaybackStereo);
outStream.writeUnsignedBits(streamFormat, 4);
outStream.writeUnsignedBits(streamRate, 2);
outStream.writeBooleanBit(isStream16BitSample);
outStream.writeBooleanBit(isStreamStereo);
outStream.writeUI16(streamSampleCount);
if (streamFormat == FORMAT_MP3) {
outStream.writeSI16(latencySeek);
}
}
void setData(byte[] data) throws IOException {
InputBitStream inStream = new InputBitStream(data);
inStream.readUnsignedBits(4); // 4 reserved bits
playbackRate = (byte) inStream.readUnsignedBits(2);
isPlayback16BitSample = inStream.readBooleanBit();
isPlaybackStereo = inStream.readBooleanBit();
streamFormat = (byte) inStream.readUnsignedBits(4);
streamRate = (byte) inStream.readUnsignedBits(2);
isStream16BitSample = inStream.readBooleanBit();
isStreamStereo = inStream.readBooleanBit();
streamSampleCount = inStream.readUI16();
if ((streamFormat == FORMAT_MP3) && (data.length > 4)) {
latencySeek = inStream.readSI16();
}
}
}