Exemple #1
0
/*
 * huffman_encode_file huffman encodes in to out.
 */
int
huffman_encode_file(FILE *in, FILE *out)
{
    SymbolFrequencies sf;
    SymbolEncoder *se;
    huffman_node *root = NULL;
    int rc;
    unsigned int symbol_count;

    /* Get the frequency of each symbol in the input file. */
    symbol_count = get_symbol_frequencies(&sf, in);

    /* Build an optimal table from the symbolCount. */
    se = calculate_huffman_codes(&sf);
    root = sf[0];

    /* Scan the file again and, using the table
       previously built, encode it into the output file. */
    rewind(in);
    rc = write_code_table(out, se, symbol_count);
    if(rc == 0)
        rc = do_file_encode(in, out, se);

    /* Free the Huffman tree. */
    free_huffman_tree(root);
    free_encoder(se);
    return rc;
}
Exemple #2
0
int huffman_encode_memory(const unsigned char *bufin,
                          unsigned int bufinlen,
                          unsigned char **pbufout,
                          unsigned int *pbufoutlen)
{
    SymbolFrequencies sf;
    SymbolEncoder *se;
    huffman_node *root = NULL;
    int rc;
    unsigned int symbol_count;
    buf_cache cache;

    /* Ensure the arguments are valid. */
    if(!pbufout || !pbufoutlen)
        return 1;

    if(init_cache(&cache, CACHE_SIZE, pbufout, pbufoutlen))
        return 1;

    /* Get the frequency of each symbol in the input memory. */
    symbol_count = get_symbol_frequencies_from_memory(&sf, bufin, bufinlen);

    /* Build an optimal table from the symbolCount. */
    se = calculate_huffman_codes(&sf);
    root = sf[0];

    /* Scan the memory again and, using the table
       previously built, encode it into the output memory. */
    rc = write_code_table_to_memory(&cache, se, symbol_count);
    if(rc == 0)
        rc = do_memory_encode(&cache, bufin, bufinlen, se);

    /* Flush the cache. */
    flush_cache(&cache);

    /* Free the Huffman tree. */
    free_huffman_tree(root);
    free_encoder(se);
    free_cache(&cache);
    return rc;
}
Exemple #3
0
/* 把 in 压缩成 out */
int huffman_encode_file(FILE *in, FILE *out)
{
    symfreq sf;
    symcode *sc;
    node *root = NULL;
    int rc;
    unsigned int syms;
    /* 获取输入文件中符号出现频率 */
    syms = get_symfreq(&sf, in);
    /* 生成编码表 */
    sc = calc_code(&sf);
    root = sf[0];
    /* 再次扫描文件,使用之前生成的编码表来编码 */
    rewind(in);
    rc = write_code_table(out, sc, syms);
    if (rc == 0)
        rc = do_file_encode(in, out, sc);
    /* 释放空间 */
    free_tree(root);
    free_encoder(sc);
    return rc;
}
Exemple #4
0
PyObject*
encoders_encode_alac(PyObject *dummy, PyObject *args, PyObject *keywds)
{

    static char *kwlist[] = {"file",
                             "pcmreader",
                             "block_size",
                             "initial_history",
                             "history_multiplier",
                             "maximum_k",
                             "minimum_interlacing_leftweight",
                             "maximum_interlacing_leftweight",
                             NULL};

    PyObject *file_obj;
    FILE *output_file;
    BitstreamWriter *output = NULL;
    pcmreader* pcmreader;
    struct alac_context encoder;
    array_ia* channels = array_ia_new();
    unsigned frame_file_offset;

    PyObject *log_output;

    init_encoder(&encoder);

    encoder.options.minimum_interlacing_leftweight = 0;
    encoder.options.maximum_interlacing_leftweight = 4;

    /*extract a file object, PCMReader-compatible object and encoding options*/
    if (!PyArg_ParseTupleAndKeywords(
                    args, keywds, "OO&iiii|ii",
                    kwlist,
                    &file_obj,
                    pcmreader_converter,
                    &pcmreader,
                    &(encoder.options.block_size),
                    &(encoder.options.initial_history),
                    &(encoder.options.history_multiplier),
                    &(encoder.options.maximum_k),
                    &(encoder.options.minimum_interlacing_leftweight),
                    &(encoder.options.maximum_interlacing_leftweight)))
        return NULL;

    encoder.bits_per_sample = pcmreader->bits_per_sample;

    /*determine if the PCMReader is compatible with ALAC*/
    if ((pcmreader->bits_per_sample != 16) &&
        (pcmreader->bits_per_sample != 24)) {
        PyErr_SetString(PyExc_ValueError, "bits per sample must be 16 or 24");
        goto error;
    }

    /*convert file object to bitstream writer*/
    if ((output_file = PyFile_AsFile(file_obj)) == NULL) {
        PyErr_SetString(PyExc_TypeError,
                        "file must by a concrete file object");
        goto error;
    } else {
        output = bw_open(output_file, BS_BIG_ENDIAN);
        bw_add_callback(output,
                        byte_counter,
                        &(encoder.mdat_byte_size));
    }

#else

int
ALACEncoder_encode_alac(char *filename,
                        FILE *input,
                        int block_size,
                        int initial_history,
                        int history_multiplier,
                        int maximum_k)
{
    FILE *output_file;
    BitstreamWriter *output = NULL;
    pcmreader *pcmreader;
    struct alac_context encoder;
    array_ia* channels = array_ia_new();
    unsigned frame_file_offset;

    init_encoder(&encoder);

    encoder.options.block_size = block_size;
    encoder.options.initial_history = initial_history;
    encoder.options.history_multiplier = history_multiplier;
    encoder.options.maximum_k = maximum_k;
    encoder.options.minimum_interlacing_leftweight = 0;
    encoder.options.maximum_interlacing_leftweight = 4;

    output_file = fopen(filename, "wb");
    /*assume CD quality for now*/
    pcmreader = open_pcmreader(input, 44100, 2, 0x3, 16, 0, 1);

    encoder.bits_per_sample = pcmreader->bits_per_sample;

    /*convert file object to bitstream writer*/
    output = bw_open(output_file, BS_BIG_ENDIAN);
    bw_add_callback(output,
                    byte_counter,
                    &(encoder.mdat_byte_size));
#endif

    /*write placeholder mdat header*/
    output->write(output, 32, 0);
    output->write_bytes(output, (uint8_t*)"mdat", 4);

    /*write frames from pcm_reader until empty*/
    if (pcmreader->read(pcmreader, encoder.options.block_size, channels))
        goto error;
    while (channels->_[0]->len > 0) {
#ifndef STANDALONE
        Py_BEGIN_ALLOW_THREADS
#endif
        /*log the number of PCM frames in each ALAC frameset*/
        encoder.frame_log->_[LOG_SAMPLE_SIZE]->append(
            encoder.frame_log->_[LOG_SAMPLE_SIZE],
            channels->_[0]->len);

        frame_file_offset = encoder.mdat_byte_size;

        /*log each frameset's starting offset in the mdat atom*/
        encoder.frame_log->_[LOG_FILE_OFFSET]->append(
            encoder.frame_log->_[LOG_FILE_OFFSET],
            frame_file_offset);

        write_frameset(output, &encoder, channels);

        /*log each frame's total size in bytes*/
        encoder.frame_log->_[LOG_BYTE_SIZE]->append(
            encoder.frame_log->_[LOG_BYTE_SIZE],
            encoder.mdat_byte_size - frame_file_offset);

#ifndef STANDALONE
        Py_END_ALLOW_THREADS
#endif

        if (pcmreader->read(pcmreader, encoder.options.block_size, channels))
            goto error;
    }

    /*return to header and rewrite it with the actual value*/
    bw_pop_callback(output, NULL);
    fseek(output_file, 0, 0);
    output->write(output, 32, encoder.mdat_byte_size);

    /*close and free allocated files/buffers,
      which varies depending on whether we're running standlone or not*/

#ifndef STANDALONE

    log_output = alac_log_output(&encoder);

    pcmreader->del(pcmreader);
    output->free(output);
    free_encoder(&encoder);
    channels->del(channels);

    return log_output;

 error:

    pcmreader->del(pcmreader);
    output->free(output);
    free_encoder(&encoder);
    channels->del(channels);

    return NULL;
}