📄 fssoundconstructor.java
字号:
public FSSoundStreamHead2 streamHeader(int samplesPerBlock)
{
return new FSSoundStreamHead2(format, sampleRate, numberOfChannels, sampleSize, sampleRate, numberOfChannels, sampleSize, samplesPerBlock, 0);
}
/**
* Generates an FSSoundStreamBlock object containing a block sound data. This method is
* used to divide the encoded sound into a sequence of blocks to allow a sound to be
* streamed to the Flash Player.
*
* If the number of samples in the last block to stream is less than the samplesPerBlock,
* the size of the FSSoundStreamBlock object is reduced accordingly. It is not padded
* to maintain the specified length.
*
* @param blockNumber the nth block of samples.
*
* @param samplesPerBlock the number of samples to stream.
*
* @return an FSSoundStreamBlock object containing a block of bytes from the encoded
* sound.
*/
public FSSoundStreamBlock streamBlock(int blockNumber, int samplesPerBlock)
{
int firstSample = 0;
int firstSampleOffset = 0;
int bytesPerBlock = 0;
int bytesRemaining = 0;
int numberOfBytes = 0;
int framesToSend = 0;
int framesSent = 0;
int frameCount = 0;
int sampleCount = 0;
int seek = 0;
byte[] bytes = null;
switch (format)
{
case FSSound.PCM:
firstSample = blockNumber * samplesPerBlock;
firstSampleOffset = firstSample * sampleSize * numberOfChannels;
bytesPerBlock = samplesPerBlock * sampleSize * numberOfChannels;
bytesRemaining = sound.length - firstSampleOffset;
numberOfBytes = (bytesRemaining < bytesPerBlock) ? bytesRemaining : bytesPerBlock;
bytes = new byte[numberOfBytes];
System.arraycopy(sound, firstSampleOffset, bytes, 0, numberOfBytes);
break;
case FSSound.ADPCM:
break;
case FSSound.MP3:
framesToSend = ((blockNumber+1) * samplesPerBlock) / samplesPerFrame;
framesSent = (blockNumber * samplesPerBlock) / samplesPerFrame;
frameCount = framesToSend - framesSent;
sampleCount = frameCount * samplesPerFrame;
seek = (blockNumber * samplesPerBlock) - (framesSent * samplesPerFrame);
numberOfBytes = 4;
for (int i=0, j=framesSent; i<frameCount; i++, j++)
numberOfBytes += frameTable[j][1];
bytes = new byte[numberOfBytes];
bytes[0] = (byte)sampleCount;
bytes[1] = (byte)(sampleCount >> 8);
bytes[2] = (byte)seek;
bytes[3] = (byte)(seek >> 8);
int offset = 4;
for (int i=0, j=framesSent; i<frameCount; i++, j++)
{
System.arraycopy(sound, frameTable[j][0], bytes, offset, frameTable[j][1]);
offset += frameTable[j][1];
}
break;
}
if (bytes != null)
return new FSSoundStreamBlock(bytes);
else
return null;
}
private void decodeWAV(String filename) throws FileNotFoundException, IOException, DataFormatException
{
FSCoder coder = new FSCoder(FSCoder.LITTLE_ENDIAN, dataFromFile(filename));
int length = 0;
int chunkType = 0;
boolean moreChunks = true;
for (int i=0; i<4; i++)
{
if (coder.readWord(1, false) != riffSignature[i])
throw new DataFormatException("Not a valid RIFF file");
}
coder.readWord(4, false);
for (int i=0; i<4; i++)
{
if (coder.readWord(1, false) != wavSignature[i])
throw new DataFormatException("Not a valid WAV file");
}
while (moreChunks)
{
chunkType = coder.readWord(4, false);
length = coder.readWord(4, false);
int blockStart = coder.getPointer();
switch (chunkType)
{
case FMT: decodeFMT(coder); break;
case DATA: decodeDATA(coder, length); length += (length % 2); break;
default: coder.adjustPointer(length << 3); break;
}
int nextBlock = blockStart + (length << 3);
/*
int bytesRead = (coder.getPointer() - blockStart) >> 3;
if (bytesRead < length)
System.err.println(chunkType + " chunk underflowed by " + (length - bytesRead) + " bytes.");
else if (bytesRead > length)
System.err.println(chunkType + " chunk overflowed by " + (bytesRead - length) + " bytes.");
*/
coder.setPointer(nextBlock);
moreChunks = coder.eof() == false;
}
}
private void decodeFMT(FSCoder coder) throws DataFormatException
{
format = FSSound.PCM;
if (coder.readWord(2, false) != 1)
throw new DataFormatException("Compressed WAV files are not currently supported.");
numberOfChannels = coder.readWord(2, false);
sampleRate = coder.readWord(4, false);
coder.readWord(4, false); // total data length
coder.readWord(2, false); // total bytes per sample
sampleSize = coder.readWord(2, false) / 8;
}
private void decodeDATA(FSCoder coder, int length)
{
samplesPerChannel = length / (sampleSize*numberOfChannels);
sound = new byte[length];
coder.readBytes(sound);
coder.adjustPointer((length % 2)*8);
}
private void decodeMP3(byte[] bytes) throws DataFormatException
{
FSCoder coder = new FSCoder(FSCoder.BIG_ENDIAN, bytes);
int numberOfFrames = 0;
int frameStart = 0;
format = FSSound.MP3;
sampleSize = 2;
while (coder.eof() == false)
{
if (coder.scanWord(3, false) == 0x494433) // ID3
{
coder.adjustPointer(24); // ID3 signature
coder.adjustPointer(8); // version number
coder.adjustPointer(8); // revision number
coder.adjustPointer(1); // unsynchronized
coder.adjustPointer(1); // extendedHeader
coder.adjustPointer(1); // experimental
int hasFooter = coder.readBits(1, false);
coder.adjustPointer(4);
int totalLength = (hasFooter == 1) ? 10 : 0;
totalLength += coder.readWord(1, false) << 23;
totalLength += coder.readWord(1, false) << 15;
totalLength += coder.readWord(1, false) << 7;
totalLength += coder.readWord(1, false);
coder.adjustPointer(totalLength<<3);
}
else if (coder.scanWord(3, false) == 0x544147) // ID3 V1
{
coder.adjustPointer(128<<3);
}
else if (coder.scanBits(11, false) == 0x7FF) // MP3 frame
{
if (numberOfFrames == 0)
frameStart = coder.getPointer();
coder.adjustPointer(MP3FrameSize(coder) << 3);
numberOfFrames++;
}
else
{
/*
* If we get here it means we jumped into the middle of either
* a frame or tag information. This appears to be a common
* occurrence. Goto the end of the file so we can keep the
* frames found so far.
*/
coder.setPointer(bytes.length<<3);
}
}
int dataLength = bytes.length - (frameStart >> 3);
sound = new byte[dataLength];
System.arraycopy(bytes, frameStart>>3, sound, 0, dataLength);
frameTable = new int[numberOfFrames][2];
for (int i=0; i<numberOfFrames; i++)
{
frameTable[i][0] = -1;
frameTable[i][1] = 0;
}
coder.setPointer(frameStart);
int frameNumber = 0;
while (coder.findBits(0x7FF, 11, 8))
{
frameTable[frameNumber][0] = (coder.getPointer()- frameStart + 16) >> 3;
coder.adjustPointer(11); // skip start of frame marker
int version = coder.readBits(2, false);
samplesPerFrame = frameSizeMP3[version];
if (coder.readBits(2, false) != 1)
throw new DataFormatException("Flash only supports MPEG Layer 3");
coder.readBits(1, false); // crc follows header
int bitRate = bitRates[version][coder.readBits(4, false)];
if (bitRate == -1)
throw new DataFormatException("Unsupported Bit-rate");
sampleRate = samplingRates[version][coder.readBits(2, false)];
if (sampleRate == -1)
throw new DataFormatException("Unsupported Sampling-rate");
int padding = coder.readBits(1, false);
coder.readBits(1, false); // reserved
numberOfChannels = channelCount[coder.readBits(2, false)];
coder.adjustPointer(6); // skip modeExtension, copyright, original and emphasis
samplesPerChannel += samplesPerFrame;
int frameSize = (((version == MPEG1) ? 144 : 72) * bitRate*1000 / sampleRate + padding) - 4;
frameTable[frameNumber++][1] = 4 + frameSize;
coder.adjustPointer(frameSize << 3);
}
}
private byte[] dataFromFile(String filename) throws IOException
{
File aFile = new File(filename);
FileInputStream imageContents = null;
byte[] bytes = new byte[(int)aFile.length()];
imageContents = new FileInputStream(aFile);
imageContents.read(bytes);
imageContents.close();
return bytes;
}
private void initFrameTable(byte[] bytes)
{
FSCoder coder = new FSCoder(FSCoder.LITTLE_ENDIAN, bytes);
coder.findBits(0x7FF, 11, 8);
int frameStart = coder.getPointer();
int numberOfFrames = 0;
while (coder.findBits(0x7FF, 11, 8))
{
coder.adjustPointer(MP3FrameSize(coder) << 3);
numberOfFrames++;
}
frameTable = new int[numberOfFrames][2];
coder.setPointer(frameStart);
int frameNumber = 0;
while (coder.findBits(0x7FF, 11, 8))
{
frameTable[frameNumber][0] = (coder.getPointer()- frameStart + 16) >> 3;
coder.adjustPointer(11); // skip start of frame marker
int version = coder.readBits(2, false);
coder.adjustPointer(3);
int bitRate = bitRates[version][coder.readBits(4, false)];
int samplingRate = samplingRates[version][coder.readBits(2, false)];
int padding = coder.readBits(1, false);
frameTable[frameNumber++][1] = 4 + (((version == MPEG1) ? 144 : 72) * bitRate*1000 / samplingRate + padding) - 4;
coder.adjustPointer((MP3FrameSize(coder) << 3)-23);
}
}
private int MP3FrameSize(FSCoder coder)
{
int frameSize = 4;
coder.adjustPointer(11);
int version = coder.readBits(2, false);
coder.adjustPointer(3);
int bitRate = bitRates[version][coder.readBits(4, false)];
int samplingRate = samplingRates[version][coder.readBits(2, false)];
int padding = coder.readBits(1, false);
coder.adjustPointer(-23);
frameSize += (((version == MPEG1) ? 144 : 72) * bitRate*1000 / samplingRate + padding) - 4;
return frameSize;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -