📄 ttadec.c
字号:
init_buffer_read(); pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->BSIZE * ttainfo->NCH; maxvalue = (1UL << ttainfo->BPS) - 1; return 0;}void close_tta_file (tta_info *info) { }void player_stop () { if (seek_table) { free(seek_table); seek_table = NULL; }}int get_samples (byte *buffer) { unsigned int k, depth, unary, binary; byte *p = buffer; decoder *dec = tta; int *prev = cache; int value, res; for (res = 0; p < buffer + pcm_buffer_size;) { fltst *fst = &dec->fst; adapt *rice = &dec->rice; int *last = &dec->last; if (data_cur == framelen) { if (data_pos == fframes) break; if (framelen && done_buffer_read()) { if (set_position(data_pos)) return -1; if (res) break; } if (data_pos == fframes - 1 && lastlen) framelen = lastlen; else framelen = ttainfo->FRAMELEN; decoder_init(tta, ttainfo->NCH, ttainfo->BSIZE); data_pos++; data_cur = 0; } // decode Rice unsigned GET_UNARY(unary); switch (unary) { case 0: depth = 0; k = rice->k0; break; default: depth = 1; k = rice->k1; unary--; } if (k) { GET_BINARY(binary, k); value = (unary << k) + binary; } else value = unary; switch (depth) { case 1: rice->sum1 += value - (rice->sum1 >> 4); if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) rice->k1--; else if (rice->sum1 > shift_16[rice->k1 + 1]) rice->k1++; value += bit_shift[rice->k0]; default: rice->sum0 += value - (rice->sum0 >> 4); if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) rice->k0--; else if (rice->sum0 > shift_16[rice->k0 + 1]) rice->k0++; } value = DEC(value); // decompress stage 1: adaptive hybrid filter hybrid_filter(fst, &value); // decompress stage 2: fixed order 1 prediction switch (ttainfo->BSIZE) { case 1: value += PREDICTOR1(*last, 4); break; // bps 8 case 2: value += PREDICTOR1(*last, 5); break; // bps 16 case 3: value += PREDICTOR1(*last, 5); break; // bps 24 } *last = value; // check for errors if (abs(value) > maxvalue) { unsigned int tail = pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res; memset(buffer, 0, pcm_buffer_size); data_cur += tail; res += tail; break; } if (dec < tta + (ttainfo->NCH - 1)) { *prev++ = value; dec++; } else { *prev = value; if (ttainfo->NCH > 1) { int *r = prev - 1; for (*prev += *r/2; r >= cache; r--) *r = *(r + 1) - *r; for (r = cache; r < prev; r++) WRITE_BUFFER(r, ttainfo->BSIZE, p) } WRITE_BUFFER(prev, ttainfo->BSIZE, p) prev = cache; data_cur++; res++; dec = tta; } } return res;}/* * Description: ID3 tags manipulation routines * Provides read access to ID3 tags v1.1, v2.3.x, v2.4.x * Supported ID3v2 frames: Title, Artist, Album, Track, * Year, Genre, Comment. * * Copyright (c) 2004 Alexander Djourik. All rights reserved. * */static unsigned int unpack_sint28 (const char *ptr) { unsigned int value = 0; if (ptr[0] & 0x80) return 0; value = value | (ptr[0] & 0x7f); value = (value << 7) | (ptr[1] & 0x7f); value = (value << 7) | (ptr[2] & 0x7f); value = (value << 7) | (ptr[3] & 0x7f); return value;}static unsigned int unpack_sint32 (const char *ptr) { unsigned int value = 0; if (ptr[0] & 0x80) return 0; value = (value << 8) | ptr[0]; value = (value << 8) | ptr[1]; value = (value << 8) | ptr[2]; value = (value << 8) | ptr[3]; return value;}static int get_frame_id (const char *id) { if (!memcmp(id, "TIT2", 4)) return TIT2; // Title if (!memcmp(id, "TPE1", 4)) return TPE1; // Artist if (!memcmp(id, "TALB", 4)) return TALB; // Album if (!memcmp(id, "TRCK", 4)) return TRCK; // Track if (!memcmp(id, "TYER", 4)) return TYER; // Year if (!memcmp(id, "TCON", 4)) return TCON; // Genre if (!memcmp(id, "COMM", 4)) return COMM; // Comment return 0;}#if 0static int skip_id3_tag (tta_info *info) { id3v2_tag id3v2; int id3v2_size; //////////////////////////////////////// // skip ID3v2 tag if (!info->Reader->Read(info->Reader, &id3v2, sizeof(id3v2_tag))) goto read_error; if (memcmp(id3v2.id, "ID3", 3)) { if (info->Reader->Seek(info->Reader, 0, SEEK_SET) < 0) goto read_error; return 0; } if (id3v2.size[0] & 0x80) goto file_error; id3v2_size = unpack_sint28(id3v2.size); id3v2_size += (id3v2.flags & ID3_FOOTERPRESENT_FLAG) ? 20 : 10; info->Reader->Seek(info->Reader, id3v2_size, SEEK_SET); info->ID3.size = id3v2_size; return id3v2_size;file_error: ttainfo->STATE = FILE_ERROR; return -1;read_error: ttainfo->STATE = READ_ERROR; return -1;}#endifstatic int read_id3_tags (tta_info *info) { id3v1_tag id3v1; id3v2_tag id3v2; id3v2_frame frame_header; int id3v2_size; char *buffer = NULL; char *ptr; //////////////////////////////////////// // ID3v1 support if (info->Reader->Seek(info->Reader, -(int) sizeof(id3v1_tag), SEEK_END) < 0) goto read_error; if (!info->Reader->Read(info->Reader, &id3v1, sizeof(id3v1_tag))) goto read_error; if (!memcmp (id3v1.id, "TAG", 3)) { memcpy(info->ID3.title, id3v1.title, 30); memcpy(info->ID3.artist, id3v1.artist, 30); memcpy(info->ID3.album, id3v1.album, 30); memcpy(info->ID3.year, id3v1.year, 4); memcpy(info->ID3.comment, id3v1.comment, 28); if (id3v1.genre > GENRES-1) id3v1.genre = 12; sprintf(info->ID3.track, "%02d", id3v1.track); if (id3v1.genre && id3v1.genre != 0xFF) sprintf(info->ID3.genre, "%s", genre[id3v1.genre]); info->ID3.id3has |= 1; } if (info->Reader->Seek(info->Reader, 0, SEEK_SET) < 0) goto read_error; //////////////////////////////////////// // ID3v2 minimal support if (!info->Reader->Read(info->Reader, &id3v2, sizeof(id3v2_tag))) goto read_error; if (memcmp(id3v2.id, "ID3", 3)) { if (info->Reader->Seek(info->Reader, 0, SEEK_SET) < 0) goto read_error; return 0; } if (id3v2.size[0] & 0x80) goto file_error; id3v2_size = unpack_sint28(id3v2.size); if (!(buffer = (unsigned char *) malloc (id3v2_size))) { ttainfo->STATE = MEMORY_ERROR; goto read_done; } if ((id3v2.flags & ID3_UNSYNCHRONISATION_FLAG) || (id3v2.flags & ID3_EXPERIMENTALTAG_FLAG) || (id3v2.version < 3)) goto read_done; if (!info->Reader->Read(info->Reader, buffer, id3v2_size)) { free (buffer); goto read_error; } ptr = buffer; // skip extended header if present if (id3v2.flags & ID3_EXTENDEDHEADER_FLAG) { int offset = unpack_sint32(ptr); ptr += offset; } // read id3v2 frames while (ptr - buffer < id3v2_size) { char *data = NULL; int data_size, frame_id; int size = 0; // get frame header memcpy(&frame_header, ptr, sizeof(id3v2_frame)); ptr += sizeof(id3v2_frame); data_size = unpack_sint32(frame_header.size); // skip unsupported frames if (!(frame_id = get_frame_id(frame_header.id)) || frame_header.flags & FRAME_COMPRESSION_FLAG || frame_header.flags & FRAME_ENCRYPTION_FLAG || frame_header.flags & FRAME_UNSYNCHRONISATION_FLAG || ( *ptr != FIELD_TEXT_ISO_8859_1 && *ptr != FIELD_TEXT_UTF_8)) { ptr += data_size; continue; } data_size--; ptr++; switch (frame_id) { case TIT2: data = info->ID3.title; size = sizeof(info->ID3.title) - 1; break; case TPE1: data = info->ID3.artist; size = sizeof(info->ID3.artist) - 1; break; case TALB: data = info->ID3.album; size = sizeof(info->ID3.album) - 1; break; case TRCK: data = info->ID3.track; size = sizeof(info->ID3.track) - 1; break; case TYER: data = info->ID3.year; size = sizeof(info->ID3.year) - 1; break; case TCON: data = info->ID3.genre; size = sizeof(info->ID3.genre) - 1; break; case COMM: data = info->ID3.comment; size = sizeof(info->ID3.comment) - 1; data_size -= 3; ptr += 3; // skip zero short description if (*ptr == 0) { data_size--; ptr++; } break; } if (data_size < size) size = data_size; memcpy(data, ptr, size); data[size] = '\0'; ptr += data_size; } info->ID3.id3has |= 2;read_done: if (buffer) free(buffer); id3v2_size += (id3v2.flags & ID3_FOOTERPRESENT_FLAG) ? 20 : 10; info->Reader->Seek(info->Reader, id3v2_size, SEEK_SET); info->ID3.size = id3v2_size; return id3v2_size;file_error: ttainfo->STATE = FILE_ERROR; return -1;read_error: ttainfo->STATE = READ_ERROR; return -1;}/* eof */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -