📄 ttadec.c
字号:
/* * ttadec.c * * Description: TTAv1 decoder library for HW players * Developed by: Alexander Djourik <ald@true-audio.com> * Pavel Zhilin <pzh@true-audio.com> * * Copyright (c) 2004 True Audio Software. All rights reserved. * *//* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the True Audio Software nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include <stdlib.h>#include <string.h>#include "ttalib.h"#include "ttadec.h"#include "filter.h"/******************* static variables and structures *******************/static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4];static unsigned char *iso_buffers_end = isobuffers + ISO_BUFFERS_SIZE;static unsigned int pcm_buffer_size;static decoder tta[MAX_NCH]; // decoder statestatic int cache[MAX_NCH]; // decoder cachetta_info *ttainfo; // currently playing file infostatic unsigned int fframes; // number of frames in filestatic unsigned int framelen; // the frame length in samplesstatic unsigned int lastlen; // the length of the last frame in samplesstatic unsigned int data_pos; // currently playing frame indexstatic unsigned int data_cur; // the playing position in framestatic int maxvalue; // output data max valuestatic unsigned int *seek_table; // the playing position tablestatic unsigned int st_state; //seek table statusstatic unsigned int frame_crc32;static unsigned int bit_count;static unsigned int bit_cache;static unsigned char *bitpos;static int read_id3_tags (tta_info *info);/************************* crc32 functions *****************************/#define UPDATE_CRC32(x, crc) crc = \ (((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF])static unsigned int crc32 (unsigned char *buffer, unsigned int len) { unsigned int i; unsigned int crc = 0xFFFFFFFF; for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc); return (crc ^ 0xFFFFFFFF);}/************************* bit operations ******************************/#define GET_BINARY(value, bits) \ while (bit_count < bits) { \ if (bitpos == iso_buffers_end) { \ if (!ttainfo->Reader->Read(ttainfo->Reader, isobuffers, \ ISO_BUFFERS_SIZE)) { \ ttainfo->STATE = READ_ERROR; \ return -1; } \ bitpos = isobuffers; } \ UPDATE_CRC32(*bitpos, frame_crc32); \ bit_cache |= *bitpos << bit_count; \ bit_count += 8; \ bitpos++; } \ value = bit_cache & bit_mask[bits]; \ bit_cache >>= bits; \ bit_count -= bits; \ bit_cache &= bit_mask[bit_count];#define GET_UNARY(value) \ value = 0; \ while (!(bit_cache ^ bit_mask[bit_count])) { \ if (bitpos == iso_buffers_end) { \ if (!ttainfo->Reader->Read(ttainfo->Reader, isobuffers, \ ISO_BUFFERS_SIZE)) { \ ttainfo->STATE = READ_ERROR; \ return -1; } \ bitpos = isobuffers; } \ value += bit_count; \ bit_cache = *bitpos++; \ UPDATE_CRC32(bit_cache, frame_crc32); \ bit_count = 8; } \ while (bit_cache & 1) { \ value++; \ bit_cache >>= 1; \ bit_count--; } \ bit_cache >>= 1; \ bit_count--;static void init_buffer_read() { frame_crc32 = 0xFFFFFFFFUL; bit_count = bit_cache = 0; bitpos = iso_buffers_end;}static int done_buffer_read() { unsigned int crc32, rbytes; frame_crc32 ^= 0xFFFFFFFFUL; rbytes = iso_buffers_end - bitpos; if (rbytes < sizeof(int)) { memcpy(isobuffers, bitpos, 4); if (!ttainfo->Reader->Read(ttainfo->Reader, isobuffers + rbytes, ISO_BUFFERS_SIZE - rbytes)) return -1; bitpos = isobuffers; } memcpy(&crc32, bitpos, 4); crc32 = ENDSWAP_INT32(crc32); bitpos += sizeof(int); if (crc32 != frame_crc32) return -1; bit_cache = bit_count = 0; frame_crc32 = 0xFFFFFFFFUL; return 0;}/************************* decoder functions ****************************/const char *get_error_str (int error) { switch (error) { case NO_ERROR: return "No errors found"; case OPEN_ERROR: return "Can't open file"; case FORMAT_ERROR: return "Not supported file format"; case FILE_ERROR: return "File is corrupted"; case READ_ERROR: return "Can't read from file"; case MEMORY_ERROR: return "Insufficient memory available"; default: return "Unknown error code"; }}int open_tta_file (tta_info *info, unsigned int data_offset) { unsigned int checksum; unsigned int datasize; unsigned int origsize; tta_hdr ttahdr; // clear the memory //memset (info, 0, sizeof(tta_info)); // get file size info->Reader->Seek(info->Reader, 0, SEEK_END); info->FILESIZE = info->Reader->FilePos; info->Reader->Seek(info->Reader, 0, SEEK_SET); // read id3 tags if (!data_offset) {// if ((data_offset = skip_id3_tag (info)) < 0) { if ((data_offset = read_id3_tags (info)) < 0) { return -1; } } else info->Reader->Seek(info->Reader, data_offset, SEEK_SET); // read TTA header if (info->Reader->Read(info->Reader, &ttahdr, sizeof (ttahdr)) == 0) { info->STATE = READ_ERROR; return -1; } // check for TTA3 signature if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) { info->STATE = FORMAT_ERROR; return -1; } ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32); checksum = crc32((unsigned char *) &ttahdr, sizeof(tta_hdr) - sizeof(int)); if (checksum != ttahdr.CRC32) { info->STATE = FILE_ERROR; return -1; } ttahdr.AudioFormat = ENDSWAP_INT16(ttahdr.AudioFormat); ttahdr.NumChannels = ENDSWAP_INT16(ttahdr.NumChannels); ttahdr.BitsPerSample = ENDSWAP_INT16(ttahdr.BitsPerSample); ttahdr.SampleRate = ENDSWAP_INT32(ttahdr.SampleRate); ttahdr.DataLength = ENDSWAP_INT32(ttahdr.DataLength); // check for player supported formats if (ttahdr.AudioFormat != WAVE_FORMAT_PCM || ttahdr.NumChannels > MAX_NCH || ttahdr.BitsPerSample > MAX_BPS ||( ttahdr.SampleRate != 16000 && ttahdr.SampleRate != 22050 && ttahdr.SampleRate != 24000 && ttahdr.SampleRate != 32000 && ttahdr.SampleRate != 44100 && ttahdr.SampleRate != 48000 && ttahdr.SampleRate != 64000 && ttahdr.SampleRate != 88200 && ttahdr.SampleRate != 96000)) { info->STATE = FORMAT_ERROR; return -1; } // fill the File Info info->NCH = ttahdr.NumChannels; info->BPS = ttahdr.BitsPerSample; info->BSIZE = (ttahdr.BitsPerSample + 7)/8; info->FORMAT = ttahdr.AudioFormat; info->SAMPLERATE = ttahdr.SampleRate; info->DATALENGTH = ttahdr.DataLength; info->FRAMELEN = (int) (FRAME_TIME * ttahdr.SampleRate); info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate; info->DATAPOS = data_offset; datasize = info->FILESIZE - info->DATAPOS; origsize = info->DATALENGTH * info->BSIZE * info->NCH; info->COMPRESS = (double) datasize / origsize; info->BITRATE = (int) (info->COMPRESS * info->SAMPLERATE * info->NCH * info->BPS / 1000); return 0;}static void rice_init(adapt *rice, unsigned int k0, unsigned int k1) { rice->k0 = k0; rice->k1 = k1; rice->sum0 = shift_16[k0]; rice->sum1 = shift_16[k1];}static void decoder_init(decoder *tta, int nch, int byte_size) { int shift = flt_set[byte_size - 1]; int i; for (i = 0; i < nch; i++) { filter_init(&tta[i].fst, shift); rice_init(&tta[i].rice, 10, 10); tta[i].last = 0; }}static void seek_table_init (unsigned int *seek_table, unsigned int len, unsigned int data_offset) { unsigned int *st, frame_len; for (st = seek_table; st < (seek_table + len); st++) { frame_len = ENDSWAP_INT32(*st); *st = data_offset; data_offset += frame_len; }}int set_position (unsigned int pos) { unsigned int seek_pos; if (pos >= fframes) return 0; if (!st_state) { ttainfo->STATE = FILE_ERROR; return -1; } seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos]; if (ttainfo->Reader->Seek(ttainfo->Reader, seek_pos, SEEK_SET) < 0) { ttainfo->STATE = READ_ERROR; return -1; } data_cur = 0; framelen = 0; // init bit reader init_buffer_read(); return 0;}int player_init (tta_info *info) { unsigned int checksum; unsigned int data_offset; unsigned int st_size; ttainfo = info; framelen = 0; data_pos = 0; data_cur = 0; lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN; fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1 : 0); st_size = (fframes + 1) * sizeof(int); seek_table = (unsigned int *) malloc(st_size); if (!seek_table) { ttainfo->STATE = MEMORY_ERROR; return -1; } // read seek table if (!info->Reader->Read(info->Reader, seek_table, st_size)) { ttainfo->STATE = READ_ERROR; return -1; } checksum = crc32((unsigned char *) seek_table, st_size - sizeof(int)); st_state = (checksum == ENDSWAP_INT32(seek_table[fframes])); data_offset = sizeof(tta_hdr) + st_size; // init seek table seek_table_init(seek_table, fframes, data_offset); // init bit reader
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -