/* * 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; }
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; }
/* 把 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; }
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; }