public boolean updateFrequencies(int[] frequencies) throws BitStreamException
    {
        if ((frequencies == null) || (frequencies.length != 256))
           return false;

        int count = 0;

        for (int i=0; i<256; i++)
        {
           this.sizes[i] = 0;
           this.codes[i] = 0;

           if (frequencies[i] > 0)
              this.ranks[count++] = i;
        }

        try
        {
           if (count == 1)
           {
              this.sranks[0] = this.ranks[0];
              this.sizes[this.ranks[0]] = 1;
           }
           else   
           {
              this.computeCodeLengths(frequencies, count);
           }
        }
        catch (IllegalArgumentException e)
        {
           // Happens when a very rare symbol cannot be coded to due code length limit
           throw new BitStreamException(e.getMessage(), BitStreamException.INVALID_STREAM);
        }

        EntropyUtils.encodeAlphabet(this.bitstream, this.ranks, count);

        // Transmit code lengths only, frequencies and codes do not matter
        // Unary encode the length difference
        ExpGolombEncoder egenc = new ExpGolombEncoder(this.bitstream, true);
        short prevSize = 2;

        for (int i=0; i<count; i++)
        {
           final short currSize = this.sizes[this.ranks[i]];
           egenc.encodeByte((byte) (currSize - prevSize));
           prevSize = currSize;
        }

        // Create canonical codes 
        if (HuffmanCommon.generateCanonicalCodes(this.sizes, this.codes, this.sranks, count) < 0)
           throw new BitStreamException("Could not generate codes: max code length (24 bits) exceeded",
                                        BitStreamException.INVALID_STREAM);

        // Pack size and code (size <= MAX_SYMBOL_SIZE bits)
        for (int i=0; i<count; i++)
        {
           final int r = this.ranks[i];
           this.codes[r] |= (this.sizes[r] << 24);           
        }

        return true;
    }