⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfwav.cpp

📁 快速哈夫曼编码,压缩性能高于普通的算术编码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                   int transform[],
                   int buffer[])
{
                                               // dyadic S+P inverse transform
  for (int lv = 5; lv >= 0; lv--) {
    int fd = ed >> lv, hd = fd >> 1;
    memcpy(buffer, transform, fd * sizeof(int));
    SpP_Synthesis(fd, buffer, buffer + hd, transform);
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Separate_Channels(unsigned od,
                       unsigned ed,
                       short * data,
                       int left[],
                       int right[])
{
  unsigned k;                  // separate interleaved left and right channels
  for (k = 0; k < od; k++) {
    left[k]  = int(*data++);
    right[k] = int(*data++);
  }
  for (k = od; k < ed; k++) {
    left[k]  = (7 * left[k-1]) >> 3;
    right[k] = (7 * right[k-1]) >> 3;
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Interleave_Channels(unsigned od,
                         int left[],
                         int right[],
                         short * data)
{
  for (unsigned k = 0; k < od; k++) {
    *data++ = short(left[k]);
    *data++ = short(right[k]);
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Encode_SpP(unsigned dim,
                int transform[],
                Binary_Codec & encoder,
                Adaptive_Huffman_Code data_model[])
{
  float ctx = 0;
  for (int k = dim - 1; k >= 0; k--) {
    int nm = int(ctx);            // context = weighted average of past values
    unsigned bits, data;
    Split_Integer(transform[k], bits, data);
    encoder.encode(bits, data_model[nm]);               // encode with context
    if (bits)                                              // write "raw" bits
      if (bits == 1)
        encoder.put_bit(data);
      else
        encoder.put_bits(data, bits);
    ctx = 0.9F * ctx + 0.2F * bits;                     // update soft context
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Decode_SpP(unsigned dim,
                Binary_Codec & decoder,
                Adaptive_Huffman_Code data_model[],
                int transform[])
{
  float ctx = 0;
  for (int k = dim - 1; k >= 0; k--) {
    int nm = int(ctx);            // context = weighted average of past values
    unsigned bits = decoder.decode(data_model[nm]);     // decode with context
    if (bits == 0)
      transform[k] = 0;
    else                                                    // read "raw" bits
      if (bits == 1)
        transform[k] = (decoder.get_bit() ? -1 : 1);
      else
        transform[k] = Restore_Integer(bits, decoder.get_bits(bits));
    ctx = 0.9F * ctx + 0.2F * bits;                     // update soft context
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

FILE * Open_Input_File(unsigned file_id,
                       char * file_name,
                       unsigned char header[44])
{
  FILE * new_file = fopen(file_name, "rb");
  if (new_file == 0) Error("cannot open input file");

  if (fread(header, 1, 44, new_file) != 44) Error(R_MSG);

  if (Recover_Number(header) != file_id)
    Error("invalid input file");

  for (unsigned n = 4; n < 44; n++)
    if ((WAVE_HEADER[n] != 0x7F) && (WAVE_HEADER[n] != header[n]))
      Error("unsupported audio file");

  return new_file;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

FILE * Open_Output_File(unsigned file_id,
                        char * file_name,
                        unsigned char header[44])
{
  FILE * new_file = fopen(file_name, "rb");
  if (new_file != 0) {
    fclose(new_file);
    printf("\n Overwrite file %s? (y = yes, otherwise quit) ", file_name);
    char line[128];
    gets(line);
    if (line[0] != 'y') exit(0);
  }

  new_file = fopen(file_name, "wb");
  if (new_file == 0) Error("cannot open output file");

  Save_Number(file_id, header);
  if (fwrite(header, 1, 44, new_file) != 44) Error(W_MSG);

  return new_file;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Encode_WAV_File(char * data_file_name,
                     char * code_file_name)
{
                                                                 // open files
  unsigned char header[44];
  FILE * data_file = Open_Input_File(WAV_ID, data_file_name, header);

  unsigned file_samples = Audio_Samples(header);
  if ((file_samples < 64) || (file_samples >= 0x10000000U))
    Error("invalid WAV file");

  FILE * code_file = Open_Output_File(HFW_ID, code_file_name, header);

                                                      // memory for audio data
  int * data = new int[3*BufferSize];
  int * left_channel   = data + BufferSize;
  int * right_channel  = data + BufferSize * 2;

  Binary_Codec encoder(5 * BufferSize);

  Adaptive_Huffman_Code * dm = new Adaptive_Huffman_Code[NumModels];
  for (unsigned m = 0; m < NumModels; m++) dm[m].set_alphabet(24);

  unsigned crc = 0;
  do {

    unsigned ns = (file_samples < BufferSize ? file_samples : BufferSize);
    unsigned es = (ns + 63) & 0xFFFFFFC0U;              // next multiple of 64
    file_samples -= ns;
    if (fread(data, 4, ns, data_file) != ns) Error(R_MSG);       // read audio

    crc ^= Buffer_CRC(4 * ns, (unsigned char *) data);          // compute CRC
    Separate_Channels(ns, es, (short*) data, left_channel, right_channel);

    SpP_Analysis(es, left_channel, data);                // compute transforms
    SpP_Analysis(es, right_channel, data);

    encoder.start_encoder();                            // prepare to compress

    Encode_SpP(es, left_channel, encoder, dm);          // compress transforms
    Encode_SpP(es, right_channel, encoder, dm);

    encoder.write_to_file(code_file);        // stop and write compressed data

  } while (file_samples);
                                                              // save file CRC
  Save_Number(crc, header);
  if (fwrite(header, 1, 4, code_file) != 4) Error(W_MSG);

                                                          // done: close files
  fflush(code_file);
  unsigned data_bytes = ftell(data_file), code_bytes = ftell(code_file);
  printf(" Compressed file size = %d bytes (%5.2f:1 compression)\n",
    code_bytes, double(data_bytes) / double(code_bytes));
  fclose(data_file);
  fclose(code_file);

  delete [] data;
  delete [] dm;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void Decode_WAV_File(char * code_file_name,
                     char * data_file_name)
{
                                                                 // open files
  unsigned char header[44];
  FILE * code_file = Open_Input_File(HFW_ID, code_file_name, header);
  FILE * data_file = Open_Output_File(WAV_ID, data_file_name, header);
  unsigned file_samples = Audio_Samples(header);

                                                      // memory for audio data
  int * data = new int[3*BufferSize];
  int * left_channel   = data + BufferSize;
  int * right_channel  = data + BufferSize * 2;

  Binary_Codec decoder(5 * BufferSize);

  Adaptive_Huffman_Code * dm = new Adaptive_Huffman_Code[NumModels];
  for (unsigned m = 0; m < NumModels; m++) dm[m].set_alphabet(24);

  unsigned crc = 0;
  do {

    unsigned ns = (file_samples < BufferSize ? file_samples : BufferSize);
    unsigned es = (ns + 63) & 0xFFFFFFC0U;              // next multiple of 64
    file_samples -= ns;

    decoder.read_from_file(code_file);  // read compressed data, start decoder

    Decode_SpP(es, decoder, dm, left_channel);        // decompress transforms
    Decode_SpP(es, decoder, dm, right_channel);

    decoder.stop_decoder();                                    // stop decoder

    SpP_Synthesis(es, left_channel, data);               // compute transforms
    SpP_Synthesis(es, right_channel, data);

    Interleave_Channels(ns, left_channel, right_channel, (short*) data);

    crc ^= Buffer_CRC(4 * ns, (unsigned char *) data);          // compute CRC

    if (fwrite(data, 4, ns, data_file) != ns) Error(W_MSG);      // read audio

  } while (file_samples);

                                                   // check if file is correct
  if (fread(header, 1, 4, code_file) != 4) Error(R_MSG);
  if (crc != Recover_Number(header)) Error("incorrect file CRC");

                                                          // done: close files
  fclose(data_file);
  fclose(code_file);

  delete [] data;
  delete [] dm;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -