Adpcm кодирование на Java

Тема в разделе "Java", создана пользователем Eugene881118, 8 июл 2008.

  1. Eugene881118

    Eugene881118 Гость

    нужно сделать программу перекодировки wav файла в bin используя алгоритм ADPCM. есть этот алгоритм написанный на яве
    Код:

    Код (Text):
    package transform.contrib;

    import com.flagstone.transform.FSCoder;

    import java.lang.*;
    import java.io.*;

    /**
    * The ADPCM class can be used to compress PCM encoded sounds to the more
    * efficient ADPCM format. ADPCM is a compressed format and Flash supports a
    * modified ADPCM algorithm with compressed samples taking 2, 3, 4 or 5 bits.
    * This results in much smaller file sizes when a movie is encoded.
    *
    * <b>Examples</b>
    *
    * The following code sample illustrates how to use the ADPCM class to add
    * sounds to a Flash file.
    *
    * int soundId = movie.newIdentifier();
    * int compressedSize = 5;
    *
    * FSSoundConstructor soundGenerator = new FSSoundConstructor("sound.wav");
    *
    * int channelCount = soundGenerator.getNumberOfChannels();
    * int sampleCount = soundGenerator.getSamplesPerChannel();
    * int sampleRate = soundGenerator.getSamplesRate();
    * int sampleSize = soundGenerator.getSamplesSize();
    *
    * byte[] compressedSound = ADPCM.compress(soundGenerator.getSound(),
    *    channelCount, sampleSize, compressedSize);
    *
    * soundGenerator.setSound(FSSound.ADPCM, channelCount, sampleCount, sampleRate,
    *    sampleSize, compressedSound);
    *
    * movie.add(soundGenerator.defineSound(soundId));
    * movie.add(new FSStartSound(FSSound(soundId, FSSound.Start)));
    *
    */
    public final class ADPCM
    {
    private static final int[] StepSize =
    {
    7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
    19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
    50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
    };

    private static final int[][] DeltaTable =
    {
    { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
    { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
    { -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
    { -1, -1, 2, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
    { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1 },
    { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 },
    };


    /**
    * Compresses a little-endian, PCM format sound to ADPCM. This method should
    * only be used with sounds in the FSSound.PCM format since the byte-order
    * in FSSound.NATIVE_PCM is platform dependent.
    *
    * @param sound an array of bytes containing the sound samples.
    *
    * @param numberOfChannels the number of channels in the sound, typically
    * 1 (mono) or 2 (stereo).
    *
    * @param sampleSize the size of each sound sample in bytes, typically 1 or 2.
    *
    * @param compressedSize the number of bits to compress each sound sample to.
    * Flash supports sample sizes in the range 2..5 bits.
    *
    * @return an array of bytes containing the compressed sound.
    */
    public static byte[] compress(byte[] sound, int numberOfChannels, int sampleSize, int compressedSize)
    {
    int samplesPerFrame = 4096;

    // Calculate size of encoded data

    int numberOfSamples = sound.length / sampleSize;
    int samplesPerChannel = numberOfSamples / numberOfChannels;
    int numberOfFrames = (samplesPerChannel + 4095) / 4096;

    int frameSize = (16 + 6 + samplesPerFrame * compressedSize) * numberOfChannels;
    int lastFrameSize = (16 + 6 + (samplesPerChannel % samplesPerFrame) * compressedSize) * numberOfChannels;
    int bytesPerFrame = (frameSize + 7) >> 3;

    byte[] out = new byte[numberOfFrames*bytesPerFrame];

    /*
    * Expand the sound data to 16-bit samples.
    */
    int[] samples = new int[numberOfSamples];

    FSCoder soundIn = new FSCoder(FSCoder.LITTLE_ENDIAN, sound);

    for (int i=0; i<numberOfSamples; i++)
    samples[i] = soundIn.readWord(sampleSize*8, true);

    /*           ВЫЛЕТАЕТ ТУТ
    * Allocate an initialize arrays to hold value, the index into the step
    * size table and the step size for the current sample in each channel.
    */
    int[] value = new int[numberOfChannels];
    int[] tableIndex = new int[numberOfChannels];
    int[] step = new int[numberOfChannels];

    for (int chan=0; chan<numberOfChannels; chan++)
    {
    value[chan] = 0;
    tableIndex[chan] = 0;
    step[chan] = 0;
    }

    int currentSample = 0;

    FSCoder compressedData = new FSCoder(FSCoder.LITTLE_ENDIAN, new byte[numberOfSamples*sampleSize]);

    /*
    * ADPCM encoded sounds in Flash start with a 2-bit field contains the
    * number of bits per sample minus 2.
    */
    compressedData.writeBits(compressedSize-2, 2);

    for (int i=0; i<samplesPerChannel-1; i++)
    {
    if (i % 4096 == 0) // start a new packet every 4096 samples
    {
    compressedData.alignToByte();

    for (int chan=0; chan<numberOfChannels; chan++, currentSample++)
    {
    value[chan] = samples[currentSample];

    int diff = Math.abs(samples[currentSample+numberOfChannels] - value[chan]);

    // Calculate initial index & step

    int index = 0;

    while (StepSize[index] < diff && index < 63)
    index ++;

    tableIndex[chan] = index;
    step[chan] = StepSize[index];

    // Write initial index into StepSizeTable

    compressedData.writeBits(value[chan], 16);
    compressedData.writeBits(tableIndex[chan], 6);
    }
    }
    else
    {
    for (int chan=0; chan<numberOfChannels; chan++, currentSample++)
    {
    // Step 1 - compute difference with previous value

    int diff = samples[currentSample] - value[chan];
    int sign = (diff < 0) ? (1 << (compressedSize-1)) : 0;

    if (sign > 0) diff = (-diff);

    // Step 2 - Divide and clamp
    int delta = 0;
    int vpdiff = step[chan] >> (compressedSize-1);

    for (int j=compressedSize-2; j>=0; j--, step[chan] >>= 1)
    {
    if (diff >= step[chan])
    {
    delta = delta | (1 << j);
    vpdiff += step[chan];

    if (j > 0)
    diff -= step[chan];
    }
    }

    // Step 3 - Update previous value
    if (sign > 0)
    value[chan] -= vpdiff;
    else
    value[chan] += vpdiff;

    // Step 4 - Clamp previous value to 16 bits
    if (value[chan] > 32767) value[chan] = 32767;
    if (value[chan] < -32768) value[chan] = -32768;

    // Step 5 - Assemble value, update index and step values

    tableIndex[chan] += DeltaTable[compressedSize][delta];

    // Clamp StepSizeTable index
    if (tableIndex[chan] < 0) tableIndex[chan] = 0;
    if (tableIndex[chan] > 88) tableIndex[chan] = 88;

    step[chan] = StepSize[tableIndex[chan]];

    // Step 6 - Output value
    compressedData.writeBits(delta |= sign, compressedSize);
    }
    }
    }

    int compressedLength = compressedData.getPointer() / 8;

    for (int i=0; i<compressedLength; i++)
    out[i] = compressedData.getData()[i];

    return out;
    }

    вот ссылка на это http://www.koders.com/java/fid26A9A93D3BEC...53ADAFC5C5.aspx
    при выполнении вылетает ошибка:
    java.lang.IllegalArgumentException: Number of bytes must be in the range 1..4.
    на другом форуме по яве посоветовали просто в строке
    Код (Text):
    samples[i] = soundIn.readWord(sampleSize*8, true);
    убрать умножение на 8 но после этого (или независимо) получается выход за границы индекса массива в строке
    Код (Text):
    tableIndex[chan] += DeltaTable[compressedSize][delta];
    стэк трейс :
    java.lang.ArrayIndexOutOfBoundsException: 5324
    at transform.contrib.ADPCM.compress(ADPCM.java:248)
    at transform.contrib.ADPCM.main(ADPCM.java:281)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
    a:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:86)


    яву изучаю второй день. незнаю что делать.
     
Загрузка...
Похожие Темы - Adpcm кодирование на
  1. Akerlem
    Ответов:
    1
    Просмотров:
    1.218
  2. Dios1986
    Ответов:
    17
    Просмотров:
    4.611

Поделиться этой страницей