Интервальный кодер

Тема в разделе "WASM.A&O", создана пользователем Proteus, 1 ноя 2007.

  1. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Кто-нибудь пробовал написать подобную вещь? Я пробую но не очень хорошо выходит. Где-то через 50 символов проиходит разнос декодера (неверно восстанавливается частота). Переполнений нигде нет! Может у кого-нибудь, как вариант, если исходник простого интервального кодера, в чистом виде (не как часть какого-либо PPM и прочего).
    Код (Text):
    1. #define CODEBITS (unsigned int)31
    2. #define TOP (1<<CODEBITS)
    3. #define BOTTOM (TOP>>8)
    4. #define BIGBYTE (0xFF<<(CODEBITS-8))
    Код (Text):
    1. void Encoder::EncodeSym(FILE *output,int sym)
    2. {
    3.    range/=cum_freq[0];
    4.    low+=cum_freq[sym] * range;
    5.    range*=freq[sym];
    6.    while(range<BOTTOM) {
    7.       if(low&BIGBYTE==BIGBYTE && range+(low&BOTTOM-1)>=BOTTOM) range=BOTTOM-(low&BOTTOM-1);
    8.          fputc(low>>24,output);
    9.       range<<=8;
    10.       low<<=8;
    11.    }
    12. }
    Код (Text):
    1. int Decoder::DecodeSym(FILE *input)
    2. {
    3.    int sym,c;
    4.    range/=cum_freq[0];
    5.    c=(value-low)/range;
    6.    for(sym=1; cum_freq[sym]>c; sym++);
    7.    low+=cum_freq[sym] * range;
    8.    range*=freq[sym];
    9.    while(range<BOTTOM) {
    10.       if(low&BIGBYTE==BIGBYTE && range+(low&BOTTOM-1)>=BOTTOM)
    11.       range=BOTTOM-(low&BOTTOM-1);
    12.       range<<=8;
    13.       low<<=8;
    14.       if(feof(input)) break;
    15.       value=(value<<8)|fgetc(input);
    16.    }
    17.    return sym;
    18. }
     
  2. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    арифметические коды что ли?
     
  3. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Нет... но принцип такой же...
     
  4. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    Предполагаю, что имеется в виду range encoding. Если это действительно так, то в сети можно найти примеры кода (начиная с ссылок в Википедии)
     
  5. CreatorCray

    CreatorCray Member

    Публикаций:
    0
    Регистрация:
    5 авг 2006
    Сообщения:
    201
    Не знаю как тебе насчет "просто"

    Код (Text):
    1. class RangeEncoder
    2. {
    3. public:
    4.     RangeEncoder(DataStreamWriter::SP writer)
    5.     {
    6.         m_cacheOrg = 0;
    7.         m_writer = writer;
    8.         m_low = 0;
    9.         m_buffer = m_count = 0;
    10.         m_range = 0xffffffff;
    11.     }
    12.  
    13.     ~RangeEncoder()
    14.     {
    15.         for (int i = 0; i < 5; i++)
    16.             Shift();
    17.         Flush ();
    18.     }
    19.  
    20.     void Encode (DWORD start, DWORD freq, DWORD total)
    21.     {
    22.         m_range /= total;
    23.         m_low += start * m_range;
    24.         m_range *= freq;
    25.         while (m_range < (1 << 24))
    26.         {
    27.             m_range <<= 8;
    28.             Shift();
    29.         }
    30.     }
    31.  
    32.     void Flush ()
    33.     {
    34.         if (m_cacheOrg)
    35.         {
    36.             m_writer->SetData (m_cache,m_cacheOrg);
    37.             m_cacheOrg = 0;
    38.         }
    39.     }
    40.  
    41. private:
    42.     QWORD   m_low;
    43.     DWORD   m_range, m_buffer, m_count;
    44.     BYTE    m_cache[RANGE_CODER_CACHE_SIZE];
    45.     DWORD   m_cacheOrg;
    46.     DataStreamWriter::SP m_writer;
    47.  
    48.     void Shift()
    49.     {
    50.         if ((m_low ^ 0xff000000) > 0x00ffffff)
    51.         {
    52.             // flush cache early if next portion may not fit
    53.  
    54.             if (m_cacheOrg >= sizeof(m_cache) - (1+m_count))
    55.                 Flush ();
    56.  
    57.             BYTE outB = (m_low >> 32);
    58.  
    59.             m_cache[m_cacheOrg++] = outB + m_buffer;
    60.  
    61.             outB += 0xff;
    62.             while (m_count > 0)
    63.             {
    64.                 m_cache[m_cacheOrg++] = outB;
    65.                 m_count--;
    66.             }
    67.             m_buffer = ((DWORD) m_low) >> 24;
    68.         }
    69.         else m_count++;
    70.         m_low = ((DWORD) m_low) << 8;
    71.     }
    72. };
    73.  
    74. class RangeDecoder
    75. {
    76. public:
    77.     RangeDecoder (DataStreamReader::SP reader)
    78.     {
    79.         m_reader = reader;
    80.  
    81.         ZeroMemory(m_cache,sizeof(m_cache));
    82.         FillCache ();
    83.  
    84.         m_range = 0xffffffff;
    85.         for (int i = 0; i < 5; i++)
    86.         {
    87.             m_buffer <<= 8;
    88.             m_buffer |= m_cache[m_cacheOrg++];
    89.         }
    90.     }
    91.  
    92.     void Update (DWORD start, DWORD freq)
    93.     {
    94.         m_buffer -= start * m_range;
    95.         m_range *= freq;
    96.         while (m_range < (1 << 24))
    97.         {
    98.             m_range <<= 8;
    99.             m_buffer <<= 8;
    100.            
    101.             if (m_cacheOrg >= m_cacheLen)
    102.                 FillCache ();
    103.  
    104.             m_buffer |= m_cache[m_cacheOrg++];
    105.         }
    106.     }
    107.  
    108.     DWORD getFreq (DWORD total)
    109.     {
    110.         m_range /= total;
    111.         return m_buffer / m_range;
    112.     }
    113.  
    114. private:
    115.     DWORD   m_range, m_buffer;
    116.     BYTE    m_cache[RANGE_CODER_CACHE_SIZE];
    117.     DWORD   m_cacheOrg, m_cacheLen;
    118.     DataStreamReader::SP m_reader;
    119.  
    120.     void FillCache ()
    121.     {
    122.         m_cacheOrg = 0;
    123.         m_cacheLen = m_reader->GetData (m_cache, sizeof (m_cache));
    124.     }
    125. };
     
  6. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    В самый раз...
     
  7. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    ТС! Compression.ru - там все есть.
     
  8. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Так как раз ничерта нет... Можно только из PPM выдирать, но это нафиг не нужно...
    С виду формулы все понятные, а когда ошибка начинает возникать, отлаживать задалбливаешься...