Index: apps/metadata/metadata_parsers.h =================================================================== --- apps/metadata/metadata_parsers.h (revision 20206) +++ apps/metadata/metadata_parsers.h (working copy) @@ -39,3 +39,4 @@ bool get_a52_metadata(int fd, struct mp3entry* id3); bool get_asf_metadata(int fd, struct mp3entry* id3); bool get_asap_metadata(int fd, struct mp3entry* id3); +bool get_tta_metadata(int fd, struct mp3entry* id3); Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 20206) +++ apps/plugins/SOURCES (working copy) @@ -28,6 +28,7 @@ #if (CONFIG_CPU == SH7034) rockbox_flash.c #endif /* CONFIG_CPU */ +test_codec.c #ifndef OLYMPUS_MROBE_500 Index: apps/metadata.c =================================================================== --- apps/metadata.c (revision 20206) +++ apps/metadata.c (working copy) @@ -115,6 +115,9 @@ /* Amiga SAP File */ [AFMT_SAP] = AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ), + /* TTA Lossless File */ + [AFMT_TTA] = + AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ), #endif }; @@ -150,17 +153,17 @@ { char *suffix; unsigned int i; - + suffix = strrchr(filename, '.'); if (suffix == NULL) { return AFMT_UNKNOWN; } - + /* skip '.' */ suffix++; - + for (i = 1; i < AFMT_NUM_CODECS; i++) { /* search extension list for type */ @@ -177,7 +180,7 @@ } while (*ext != '\0'); } - + return AFMT_UNKNOWN; } @@ -340,7 +343,7 @@ DEBUGF("get_adx_metadata error\n"); return false; } - + break; case AFMT_NSF: @@ -362,7 +365,7 @@ } break; - + case AFMT_SAP: if (!get_asap_metadata(fd, id3)) { @@ -372,11 +375,21 @@ id3->filesize = filesize(fd); id3->genre_string = id3_get_num_genre(36); break; - + + case AFMT_TTA: + if (!get_tta_metadata(fd, id3)) + { + DEBUGF("get_tta_metadata error\n"); + return false; + } + id3->filesize = filesize(fd); + id3->genre_string = id3_get_num_genre(36); + break; + #endif /* CONFIG_CODEC == SWCODEC */ - + default: - /* If we don't know how to read the metadata, assume we can't play + /* If we don't know how to read the metadata, assume we can't play the file */ return false; break; @@ -390,7 +403,7 @@ id3->cuesheet_type = 1; } #endif - + lseek(fd, 0, SEEK_SET); strncpy(id3->path, trackname, sizeof(id3->path)); @@ -402,7 +415,7 @@ void strip_tags(int handle_id) { static const unsigned char tag[] = "TAG"; - static const unsigned char apetag[] = "APETAGEX"; + static const unsigned char apetag[] = "APETAGEX"; size_t len, version; void *tail; Index: apps/metadata.h =================================================================== --- apps/metadata.h (revision 20206) +++ apps/metadata.h (working copy) @@ -61,6 +61,7 @@ AFMT_WMA, /* WMAV1/V2 in ASF */ AFMT_MOD, /* Amiga MOD File Format */ AFMT_SAP, /* Amiga 8Bit SAP Format */ + AFMT_TTA, /* TTA lossless format */ #endif /* add new formats at any index above this line to have a sensible order - @@ -108,7 +109,7 @@ REC_FORMAT_CFG_NUM_BITS = 2 }; -#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3" +#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3" /* get REC_FORMAT_* corresponding AFMT_* */ extern const int rec_format_afmt[REC_NUM_FORMATS]; @@ -170,7 +171,7 @@ char* comment; char* albumartist; char* grouping; - int discnum; + int discnum; int tracknum; int version; int layer; @@ -221,9 +222,9 @@ long playcount; long lastplayed; long playtime; - + /* replaygain support */ - + #if CONFIG_CODEC == SWCODEC char* track_gain_string; char* album_gain_string; Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 20206) +++ apps/SOURCES (working copy) @@ -157,6 +157,7 @@ metadata/wavpack.c metadata/a52.c metadata/asap.c +metadata/tta.c #endif #ifdef HAVE_TAGCACHE tagcache.c Index: apps/filetypes.c =================================================================== --- apps/filetypes.c (revision 20206) +++ apps/filetypes.c (working copy) @@ -83,6 +83,7 @@ { "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, { "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, { "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, + { "tta" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, #endif { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, @@ -122,7 +123,7 @@ struct file_type { int icon; /* the icon which shall be used for it, NOICON if unknown */ - unsigned char attr; /* FILETYPES_MASK >> 8 */ + unsigned char attr; /* FILETYPES_MASK >> 8 */ char* plugin; /* Which plugin to use, NULL if unknown, or builtin */ char* extension; /* NULL for none */ }; @@ -156,7 +157,7 @@ for (i = 0; i < MAX_FILETYPES+1; i++) { custom_colors[i] = -1; } - snprintf(buffer, MAX_PATH, "%s/%s.colours", THEME_DIR, + snprintf(buffer, MAX_PATH, "%s/%s.colours", THEME_DIR, global_settings.colors_file); fd = open(buffer, O_RDONLY); if (fd < 0) @@ -202,8 +203,8 @@ { custom_filetype_icons[i] = filetypes[i].icon; } - - snprintf(buffer, MAX_PATH, "%s/%s.icons", ICON_DIR, + + snprintf(buffer, MAX_PATH, "%s/%s.icons", ICON_DIR, global_settings.viewers_icon_file); fd = open(buffer, O_RDONLY); if (fd < 0) @@ -244,7 +245,7 @@ filetypes[0].plugin = NULL; filetypes[0].attr = 0; filetypes[0].icon = Icon_Folder; - + filetype_count = 1; read_builtin_types(); read_config(VIEWERS_CONFIG); @@ -294,7 +295,7 @@ int fd = open(config_file, O_RDONLY); if (fd < 0) return; - /* config file is in the for + /* config file is in the for ,, ignore line if either of the first two are missing */ while (read_line(fd, line, 64) > 0) @@ -312,14 +313,14 @@ continue; *e = '\0'; strcpy(extension, s); - + /* get the plugin */ s = e+1; e = strchr(s, ','); if (!e) continue; *e = '\0'; - + strcpy(plugin, s); /* ok, store this plugin/extension, check icon after */ filetypes[filetype_count].extension = filetypes_strdup(extension); @@ -348,7 +349,7 @@ extension++; for (i=0; i + * Pavel Zhilin + * + * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved. + * + */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Please see the file COPYING in this directory for full copyright + * information. + */ + +#ifndef CRC32_H +#define CRC32_H + +const unsigned long crc32_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +#define UPDATE_CRC32(x, crc) crc = \ + (((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF]) + + + +#endif /* CRC32_H */ Property changes on: apps/codecs/libtta/crc32.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/SOURCES =================================================================== --- apps/codecs/libtta/SOURCES (revision 0) +++ apps/codecs/libtta/SOURCES (revision 0) @@ -0,0 +1 @@ +ttadec.c Property changes on: apps/codecs/libtta/SOURCES ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/ttadec.c =================================================================== --- apps/codecs/libtta/ttadec.c (revision 0) +++ apps/codecs/libtta/ttadec.c (revision 0) @@ -0,0 +1,510 @@ +/* + * ttadec.c + * + * Description: TTAv1 decoder library for HW players. + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved. + * + */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Please see the file COPYING in this directory for full copyright + * information. + */ +#include "codeclib.h" +#include +#include +#include + +#include "ttalib.h" +#include "ttadec.h" +#include "crc32.h" +#include "filters.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 long pcm_buffer_size; + +static decoder tta[MAX_NCH]; // decoder state +static long cache[MAX_NCH]; // decoder cache + +tta_info *ttainfo; // currently playing file info + +static unsigned long fframes; // number of frames in file +static unsigned long framelen; // the frame length in samples +static unsigned long lastlen; // the length of the last frame in samples +static unsigned long data_pos; // currently playing frame index +static unsigned long data_cur; // the playing position in frame + +static long maxvalue; // output data max value +static unsigned int *seek_table; // the playing position table +#define SEEK_SIZE 65536 +static char seek_table_buf[SEEK_SIZE]; // +static unsigned long st_state; //seek table status + +static unsigned long frame_crc32; +static unsigned long bit_count; +static unsigned long bit_cache; +static unsigned char *bitpos; +static unsigned long bitrate; + +void get_id3v1_tag (tta_info *ttainfo); +int get_id3v2_tag (tta_info *ttainfo); + +/************************* bit operations ******************************/ + +static void init_buffer_read() { + frame_crc32 = 0xFFFFFFFFUL; + bit_count = bit_cache = 0; + bitpos = iso_buffers_end; +} + +__inline void get_binary(unsigned long *value, unsigned long bits) { + while (bit_count < bits) { + + //TODO: don't check if the buffer is empty every bit + + //TODO: determine if its really worth copying memory to isobuffers + + //this seems to fail. maybe we should just have this function request a new buffer directly + + if (bitpos == iso_buffers_end) { + int size; + DEBUGF("resizing: %d %d\n",ISO_BUFFERS_SIZE, ttainfo->bufremain); /*this doesn't work right for some reason, probably*/ + if(ISO_BUFFERS_SIZEbufremain) + size=ISO_BUFFERS_SIZE; + else + size=ttainfo->bufremain; + + memcpy(isobuffers, ttainfo->databuf, size); + ttainfo->bufremain -= size; + DEBUGF("bufremain: %d\n", ttainfo->bufremain); + //DEBUGF("%c% + //exit(0); + //long res = fread(isobuffers, 1,ISO_BUFFERS_SIZE, ttainfo->HANDLE); + + /*if (!res) { + ttainfo->STATE = READ_ERROR; + return; + }*/ + 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]; +} +/*BROKEN!!!*/ +__inline void get_unary(unsigned long *value) { + *value = 0; + while (!(bit_cache ^ bit_mask[bit_count])) { + if (bitpos == iso_buffers_end) { + int size; + if(ISO_BUFFERS_SIZEbufremain) + size=ISO_BUFFERS_SIZE; + else + size=ttainfo->bufremain; + + memcpy(isobuffers, ttainfo->databuf, size); + ttainfo->bufremain -= size; + + /*long res = fread(isobuffers, 1,ISO_BUFFERS_SIZE, ttainfo->HANDLE); + if (!res) { + ttainfo->STATE = READ_ERROR; + return; + } + */ + bitpos = isobuffers; + + } + //DEBUGF("bit_count: %x bit_cache: %x\n", bit_count, bit_cache); + *value += bit_count; + bit_cache = *bitpos++; //BITPOS GIVES ME THE WRONG FUCKING DATA + DEBUGF("bit_cache2: %x\n", bit_cache); + UPDATE_CRC32(bit_cache, frame_crc32); + bit_count = 8; + } + //exit(0); + + while (bit_cache & 1) { + (*value)++; + bit_cache >>= 1; + bit_count--; + } + + bit_cache >>= 1; + bit_count--; +} + +static long done_buffer_read() { + unsigned long crc32, rbytes, res; + frame_crc32 ^= 0xFFFFFFFFUL; + + rbytes = iso_buffers_end - bitpos; + if (rbytes < sizeof(long)) { + memcpy(isobuffers, bitpos, 4); + //res = fread(isobuffers + rbytes, 1,ISO_BUFFERS_SIZE - rbytes, ttainfo->HANDLE); + int size; + if(ISO_BUFFERS_SIZE-4bufremain) + size=ISO_BUFFERS_SIZE-4; + else + size=ttainfo->bufremain; + + memcpy(isobuffers+rbytes, ttainfo->databuf, size); + + + /* + if (!res) { + ttainfo->STATE = READ_ERROR; + return 0; + } + */ + bitpos = isobuffers; + } + + memcpy(&crc32, bitpos, 4); + crc32 = ENDSWAP_INT32(crc32); + bitpos += sizeof(long); + res = (crc32 != frame_crc32); + + bit_cache = bit_count = 0; + frame_crc32 = 0xFFFFFFFFUL; + + // calculate dynamic bitrate + if (data_pos < fframes) { + rbytes = seek_table[data_pos] - + seek_table[data_pos - 1]; + bitrate = (rbytes << 3) / 1070; + } + + return res; +} + +#if 0 +/************************* decoder functions ****************************/ + +static long skip_id3v2_header (FILE *infile) { + struct { + unsigned char id[3]; + unsigned short version; + unsigned char flags; + unsigned char size[4]; + } __ATTRIBUTE_PACKED__ id3v2; + unsigned long len = 0; + + // read ID3V2 header + if (fread (&id3v2, sizeof(id3v2), 1, infile) == 0) { + fclose (infile); + ttainfo->STATE = READ_ERROR; + return -1; + } + + // skip ID3V2 header + if (!memcmp (id3v2.id, "ID3", 3)) { + if (id3v2.size[0] & 0x80) { + fclose (infile); + ttainfo->STATE = FILE_ERROR; + return FILE_ERROR; + } + len = (id3v2.size[0] & 0x7f); + len = (len << 7) | (id3v2.size[1] & 0x7f); + len = (len << 7) | (id3v2.size[2] & 0x7f); + len = (len << 7) | (id3v2.size[3] & 0x7f); + len += 10; + if (id3v2.flags & (1 << 4)) len += 10; + fseek (infile, len, SEEK_SET); + } else fseek (infile, 0, SEEK_SET); + + return len; +} +#endif + + +static void rice_init(adapt *rice, unsigned long k0, unsigned long k1) { + rice->k0 = k0; + rice->k1 = k1; + rice->sum0 = shift_16[k0]; + rice->sum1 = shift_16[k1]; +} + +static void decoder_init(decoder *tta, long nch, long byte_size) { + long shift = flt_set[byte_size - 1]; + long 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 long *seek_table, + unsigned long len, unsigned long data_offset) { + unsigned long *st, frame_len; + + for (st = seek_table; st < (seek_table + len); st++) { + frame_len = ENDSWAP_INT32(*st); + *st = data_offset; + data_offset += frame_len; + } +} + +long set_position (unsigned long pos) { + unsigned long seek_pos; + + if (pos >= fframes) return 0; + if (!st_state) { + ttainfo->STATE = FILE_ERROR; + DEBUGF("errored out of set_position\n"); + return -1; + } + + seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos]; + DEBUGF("tried to fseek to offset %d\n", seek_pos); + //fseek(ttainfo->HANDLE, seek_pos, SEEK_SET); + + data_cur = 0; + framelen = 0; + + // init bit reader + init_buffer_read(); + + return 0; +} + +long player_init (tta_info *info, char *seekbuf) { + unsigned long checksum; + unsigned long data_offset; + unsigned long st_size; + + ttainfo = info; + + framelen = 0; + data_pos = 0; + data_cur = 0; + bitrate = 0; + + lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN; + fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1:0); + st_size = (fframes + 1) * sizeof(int); + + seek_table = (unsigned int *)&seek_table_buf; + if (st_size>SEEK_SIZE) { + DEBUGF("seek table too large to fit: %d bytes\n", st_size); + ttainfo->STATE = MEMORY_ERROR; + return -1; + } + + // read seek table + /* + if (!fread(seek_table, st_size, 1, ttainfo->HANDLE)) { + ttainfo->STATE = READ_ERROR; + return -1; + } + */ + memcpy(seek_table, seekbuf, st_size); + + 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; + + DEBUGF("fframes: %d\n", fframes); + DEBUGF("st_state: %x checksum: %x, ENDSWAP: %d\n",st_state, checksum, (st_size)); + DEBUGF("st_size: %d\n", st_size); + if(st_state != 1){ + DEBUGF("Exit: st_state: %x checksum: %x, ENDSWAP: %x\n",st_state, checksum, ENDSWAP_INT32(seek_table[fframes])); + DEBUGF("first word: %x\n", (unsigned int)*seek_table); + exit(0); + } + + // init seek table + seek_table_init(seek_table, fframes, data_offset); + + // init bit reader + init_buffer_read(); + + pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->BSIZE * ttainfo->NCH; //20kb is typical + maxvalue = (1UL << ttainfo->BPS) - 1; + DEBUGF("pcm_buffer_size is %d bytes\n", pcm_buffer_size); + + return 0; +} +/* +void close_tta_file (tta_info *info) { + if (info->HANDLE) { + fclose (info->HANDLE); + info->HANDLE = NULL; + } +} + +void player_stop () { + if (seek_table) { + free(seek_table); + seek_table = NULL; + } +} +*/ +long get_bitrate () { + return bitrate; +} +#if 1 +long get_samples (char *buffer, char* compressbuf, int buflength, int *bufadvance) { + unsigned long k, depth, unary, binary; + byte *p = buffer; + decoder *dec = tta; + long *prev = cache; + int value, res; + + /*init the compressed audio buffer*/ + ttainfo->databuf=compressbuf; + ttainfo->bufremain=buflength; + DEBUGF("\n\n\n"); + for (res = 0; p < buffer + pcm_buffer_size;) { + DEBUGF("res: %d p: %x, buffer+pcmbuffer: %x\n", res, p, buffer + pcm_buffer_size); + if(res> 713) exit(0); + fltst *fst = &dec->fst; + adapt *rice = &dec->rice; + long *last = &dec->last; + + if (data_cur == framelen) { + if (data_pos == fframes) break; + if (framelen && done_buffer_read()) { + if (set_position(data_pos) < 0){ /*I think this is some sort of error resilance code?*/ + DEBUGF("hit set_position related branch\n"); + + 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; + } + //DEBUGF("here1\n"); + // decode Rice unsigned + get_unary(&unary); + //DEBUGF("get unary: %x\n", unary); + + switch (unary) { + case 0: depth = 0; k = rice->k0; break; + default: + depth = 1; k = rice->k1; + unary--; + } + + if (k) { + //DEBUGF("IFF\n"); + get_binary(&binary, k); //this is probably broken + //DEBUGF("IFF binary: %d %d\n", binary, k); + value = (unary << k) + binary; + } else + value = unary; + + DEBUGF("value1: %d\n", value); + 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); + DEBUGF("value2: %d, last: %d\n", value, *last); + // decompress stage 1: adaptive hybrid filter + hybrid_filter(fst, &value); //this still doesn't work + //DEBUGF("value2a: %d, last: %d\n", value, *last); + // 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 + case 4: value += *last; break; // bps 32 + } *last = value; + + DEBUGF("value3: %d\n", value); + // check for errors + //DEBUGF("abs(value): %d maxvalue: %d\n", abs(value), maxvalue); + if (abs(value) > maxvalue) { + + unsigned long tail = + pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res; + memset(buffer, 0, pcm_buffer_size); + data_cur += tail; res += tail; + break; + } + //DEBUGF("here3\n"); + if (dec < tta + (ttainfo->NCH - 1)) { + //DEBUGF("IF\n"); + *prev++ = value; dec++; + } else { + //DEBUGF("ELSE\n"); + *prev = value; + if (ttainfo->NCH > 1) { + long *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; + } + //DEBUGF("here4\n"); + } + *bufadvance=buflength-ttainfo->bufremain; + DEBUGF("return==> res: %d p: %x, buffer+pcmbuffer: %x\n", res, p, buffer + pcm_buffer_size); + return res; +} +#endif +/* end */ + unsigned long crc32 (unsigned char *buffer, unsigned long len) { + unsigned long i; + unsigned long crc = 0xFFFFFFFF; + + for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc); + + return (crc ^ 0xFFFFFFFF); +} \ No newline at end of file Property changes on: apps/codecs/libtta/ttadec.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/ttalib.h =================================================================== --- apps/codecs/libtta/ttalib.h (revision 0) +++ apps/codecs/libtta/ttalib.h (revision 0) @@ -0,0 +1,182 @@ +/* + * ttalib.h + * + * Description: TTAv1 player library prototypes + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved. + * + */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Please see the file COPYING in this directory for full copyright + * information. + */ + +#ifndef TTALIB_H_ +#define TTALIB_H_ + +#include "id3tag.h" +#include "inttypes.h" + +//#define _BIG_ENDIAN +#define MAX_BPS 24 // Max supported Bit resolution +#define MAX_NCH 8 // Max supported number of channels + +// return codes +#define NO_ERROR 0 +#define OPEN_ERROR 1 // Can't open file +#define FORMAT_ERROR 2 // Unknown TTA format version +#define PLAYER_ERROR 3 // Not supported file format +#define FILE_ERROR 4 // File is corrupted +#define READ_ERROR 5 // Can't read from file +#define MEMORY_ERROR 6 // Insufficient memory available + +#define FRAME_TIME 1.04489795918367346939 +#define SEEK_STEP (int)(FRAME_TIME * 1000) + +#define ISO_BUFFER_LENGTH (1024) +#define ISO_NBUFFERS (2) +#define ISO_BUFFERS_SIZE (ISO_BUFFER_LENGTH*ISO_NBUFFERS) +#define PCM_BUFFER_LENGTH (4608) + +typedef struct { + //FILE *HANDLE; // file handle + uint8_t *databuf; // compressed data + uint32_t bufremain; // remaining compressed data + unsigned short NCH; // number of channels + unsigned short BPS; // bits per sample + unsigned short BSIZE; // byte size + unsigned short FORMAT; // audio format + unsigned long SAMPLERATE; // samplerate (sps) + unsigned long DATALENGTH; // data length in samples + unsigned long FRAMELEN; // frame length + unsigned long LENGTH; // playback time (sec) + unsigned long STATE; // return code + unsigned long DATAPOS; // size of ID3v2 header + id3v1_data id3v1; + id3v2_data id3v2; +} tta_info; + + +typedef struct { + uint32_t TTAid; + uint16_t AudioFormat; + uint16_t NumChannels; + uint16_t BitsPerSample; + uint32_t SampleRate; + uint32_t DataLength; + uint32_t CRC32; +} tta_hdr; + + +#ifdef _BIG_ENDIAN +#define ENDSWAP_INT16(x) (((((x)>>8)&0xFF)|(((x)&0xFF)<<8))) +#define ENDSWAP_INT32(x) (((((x)>>24)&0xFF)|(((x)>>8)&0xFF00)|(((x)&0xFF00)<<8)|(((x)&0xFF)<<24))) +#define WRITE_BUFFER(x, bsize, out) { \ + if (bsize > 2) *out++ = (byte)(*x >> 16); \ + if (bsize > 1) *out++ = (byte)(*x >> 8); \ + *out++ = (byte) *x; } +#else +#define ENDSWAP_INT16(x) (x) +#define ENDSWAP_INT32(x) (x) +#define WRITE_BUFFER(x, bsize, out) { \ + *out++ = (byte) *x; \ + if (bsize > 1) *out++ = (byte)(*x >> 8); \ + if (bsize > 2) *out++ = (byte)(*x >> 16); } +#endif + +#define PREDICTOR1(x, k) ((int)((((uint64_t)x << k) - x) >> k)) +#define DEC(x) (((x)&1)?(++(x)>>1):(-(x)>>1)) + +#define TTA1_SIGN 0x31415454 + + +/*********************** Library functions *************************/ + +#ifdef LIBTEST +#ifndef DPRINTF +#define DPRINTF(x) fprintf(stderr, (x)) +#endif /* DPRINTF */ + +static void tta_error (int error) { + DPRINTF("TTA Decoder Error - "); + switch (error) { + case OPEN_ERROR: DPRINTF("Can't open file\n"); break; + case FORMAT_ERROR: DPRINTF("Not supported file format\n"); break; + case FILE_ERROR: DPRINTF("File is corrupted\n"); break; + case READ_ERROR: DPRINTF("Can't read from file\n"); break; + case MEMORY_ERROR: DPRINTF("Insufficient memory available\n"); break; + } +} +#endif /* LIBTEST */ + +long open_tta_file ( // FUNCTION: opens TTA file + const char *filename, // file to open + tta_info *info, // file info structure + unsigned long offset); // ID3v2 header size +/* + * RETURN VALUE + * This function returns 0 if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +void close_tta_file ( // FUNCTION: closes currently playing file + tta_info *info); // file info structure + +long set_position ( // FUNCTION: sets playback position + unsigned long pos); // seek position = seek_time_ms / SEEK_STEP +/* + * RETURN VALUE + * This function returns 0 if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +long player_init ( // FUNCTION: initializes TTA player + tta_info *info, // file info structure + char *seekbuf); //the seek table from the codec buffer +/* + * RETURN VALUE + * This function returns 0 if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +void player_stop (void); // FUNCTION: destroys memory pools + +long get_samples ( // FUNCTION: decode PCM_BUFFER_LENGTH samples + char *pcmbuffer, char *compressedbuf, int buflength, int *bufadvance); // into the current PCM buffer position +/* + * RETURN VALUE + * This function returns the number of samples successfully decoded. + * Otherwise, -1 is returned and the variable STATE of the currently + * using info structure is set to indicate the error. + * + */ + +long get_bitrate (void); // RETURN VALUE: TTA dynamic bitrate + +unsigned long crc32 (unsigned char *buffer, unsigned long len); + +#endif /* TTALIB_H_ */ + Property changes on: apps/codecs/libtta/ttalib.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/ttaplayer.c =================================================================== --- apps/codecs/libtta/ttaplayer.c (revision 0) +++ apps/codecs/libtta/ttaplayer.c (revision 0) @@ -0,0 +1,157 @@ +/* + * ttaplayer.c + * + * Description: TTA player library sample + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 2004 Alexander Djourik. All rights reserved. + * + */ + +#pragma pack (1) +#define LIBTEST + +#include +#include +#include +#include +#include "../ttalib.h" + +#define RIFF_SIGN (0x46464952) +#define WAVE_SIGN (0x45564157) +#define fmt_SIGN (0x20746D66) +#define data_SIGN (0x61746164) +#define MAX_BSIZE (MAX_BPS>>3) + +static char sample_buffer[PCM_BUFFER_LENGTH * MAX_BSIZE * MAX_NCH]; +static tta_info info; // currently playing file info + +/////////////////////////////////////////////////////////////////// +//
- decode data and put pcm samples into the file out.wav +/////////////////////////////////////////////////////////////////// +int main ( int argc, char **argv) { + FILE *fdout; + int i, data_size; + struct { + unsigned int ChunkID; + unsigned int ChunkSize; + unsigned int Format; + unsigned int Subchunk1ID; + unsigned int Subchunk1Size; + unsigned short AudioFormat; + unsigned short NumChannels; + unsigned int SampleRate; + unsigned int ByteRate; + unsigned short BlockAlign; + unsigned short BitsPerSample; + } wave_hdr; + struct { + unsigned int SubchunkID; + unsigned int SubchunkSize; + } subchunk_hdr; + int counter = 0; + time_t stop, start = time (NULL); + + if (argc < 2) { + printf ("\nUsage: player infile\n"); + exit (0); + } + + //////////////////////////////////////// + // open TTA file + if (open_tta_file (argv[1], &info, 0) < 0) { + printf("\nTTA Decoder Error - %s\n", + get_error_str(info.STATE)); + close_tta_file (&info); + exit(0); + } + + //////////////////////////////////////// + // initialize TTA player + if (player_init(&info) < 0) { + printf("\nTTA Decoder Error - %s\n", + get_error_str(info.STATE)); + close_tta_file (&info); + exit(0); + } + + fdout = fopen ("out.wav", "wb"); + if (!fdout) { + close_tta_file (&info); + exit(0); + } + + // Show file info + printf ("\nDecode file:\t\t[%s]\n\n", argv[1]); + printf ("File size:\t\t[%.2f Mb]\n", info.FILESIZE / 1048576.); + printf ("Number of channels:\t[%d]\n", (int) info.NCH); + printf ("Bits per sample:\t[%d]\n", (int) info.BPS); + printf ("Audio format:\t\t[%d]\n", (int) info.FORMAT); + printf ("Samplerate:\t\t[%d]\n", info.SAMPLERATE); + printf ("Playback time:\t\t[%d:%02d]\n", + info.LENGTH / 60, info.LENGTH % 60); + printf ("Average bitrate:\t[%d Kbps]\n", info.BITRATE); + printf ("Compression ratio:\t[%.2f]\n", info.COMPRESS); + + printf ("\nTitle:\t\t\t[%s]\n", info.ID3.title); + printf ("Artist:\t\t\t[%s]\n", info.ID3.artist); + printf ("Album:\t\t\t[%s]\n", info.ID3.album); + printf ("Track:\t\t\t[%s]\n", info.ID3.track); + printf ("Year:\t\t\t[%s]\n", info.ID3.year); + printf ("Genre:\t\t\t[%s]\n", info.ID3.genre); + printf ("Comment:\t\t[%s]\n\n", info.ID3.comment); + + data_size = info.DATALENGTH * info.BSIZE * info.NCH; + memset (&wave_hdr, 0, sizeof (wave_hdr)); + wave_hdr.ChunkID = RIFF_SIGN; + wave_hdr.ChunkSize = data_size + 36; + wave_hdr.Format = WAVE_SIGN; + wave_hdr.Subchunk1ID = fmt_SIGN; + wave_hdr.Subchunk1Size = 16; + wave_hdr.AudioFormat = 1; + wave_hdr.NumChannels = (unsigned short) info.NCH; + wave_hdr.SampleRate = info.SAMPLERATE; + wave_hdr.BitsPerSample = info.BPS; + wave_hdr.ByteRate = info.SAMPLERATE * info.BSIZE * info.NCH; + wave_hdr.BlockAlign = (unsigned short)(info.NCH * info.BSIZE); + subchunk_hdr.SubchunkID = data_SIGN; + subchunk_hdr.SubchunkSize = data_size; + + // write WAVE header + fwrite (&wave_hdr, sizeof (wave_hdr), 1, fdout); + + // write Subchunk header + fwrite (&subchunk_hdr, sizeof (subchunk_hdr), 1, fdout); + + //////////////////////////////////////// + // decode PCM_BUFFER_LENGTH samples + // into the current PCM buffer position + while ((i = get_samples (sample_buffer))) { + if (i < 0) { + printf("\nTTA Decoder Error - %s\n", + get_error_str(info.STATE)); + break; + } + + counter += i; + fwrite (sample_buffer, i * info.NCH, info.BSIZE, fdout); + fprintf (stderr, "Process:\t\t[%d%%]\r", + (int)((double)counter/info.DATALENGTH * 100)); + } + + //////////////////////// + // destroy memory pools + player_stop (); + + /////////////////////////////// + // close currently playing file + close_tta_file (&info); + + fclose (fdout); + stop = time (NULL); + + printf ("\nDecode time:\t\t[%02ds]\n\n", (int)(stop - start)); + exit (0); +} + Property changes on: apps/codecs/libtta/ttaplayer.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/ttadec.h =================================================================== --- apps/codecs/libtta/ttadec.h (revision 0) +++ apps/codecs/libtta/ttadec.h (revision 0) @@ -0,0 +1,122 @@ +/* + * ttadec.h + * + * Description: TTAv1 decoder definitions and prototypes + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved. + * + */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Please see the file COPYING in this directory for full copyright + * information. + */ + +#include "inttypes.h" + +#ifndef TTADEC_H_ +#define TTADEC_H_ + +#ifdef _WIN32 +#pragma pack(1) +#define __ATTRIBUTE_PACKED__ +#else +#define __ATTRIBUTE_PACKED__ __attribute__((packed)) +#endif + + +#define FRAME_TIME 1.04489795918367346939 +#define MAX_ORDER 8 + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_PCM 1 +#endif + + + +const unsigned long bit_mask[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +const unsigned long bit_shift[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 +}; + +const unsigned long *shift_16 = bit_shift + 4; + +typedef unsigned char byte; + + +/* +typedef struct { + unsigned long TTAid; + unsigned short AudioFormat; + unsigned short NumChannels; + unsigned short BitsPerSample; + unsigned long SampleRate; + unsigned long DataLength; + unsigned long CRC32; +} __ATTRIBUTE_PACKED__ tta_hdr; +*/ + + + + + +typedef struct { + unsigned long k0; + unsigned long k1; + unsigned long sum0; + unsigned long sum1; +} adapt; + +typedef struct { + int shift; + int round; + int error; + int mutex; + int qm[MAX_ORDER+1]; + int dx[MAX_ORDER+1]; + int dl[MAX_ORDER+1]; +} fltst; + +typedef struct { + fltst fst; + adapt rice; + long last; +} decoder; + +#endif /* TTADEC_H_ */ Property changes on: apps/codecs/libtta/ttadec.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/libtta.make =================================================================== --- apps/codecs/libtta/libtta.make (revision 0) +++ apps/codecs/libtta/libtta.make (revision 0) @@ -0,0 +1,18 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# + +# libtta +TTALIB := $(CODECDIR)/libtta.a +TTALIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libtta/SOURCES) +TTALIB_OBJ := $(call c2obj, $(TTALIB_SRC)) +OTHER_SRC += $(TTALIB_SRC) + +$(TTALIB): $(TTALIB_OBJ) + $(SILENT)$(shell rm -f $@) + $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null Property changes on: apps/codecs/libtta/libtta.make ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtta/filters.h =================================================================== --- apps/codecs/libtta/filters.h (revision 0) +++ apps/codecs/libtta/filters.h (revision 0) @@ -0,0 +1,110 @@ +/* + * filters.h + * + * Description: TTAv1 filter functions + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved. + * + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * aint with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please see the file COPYING in this directory for full copyright + * information. + */ + +#ifndef FILTERS_H +#define FILTERS_H + +///////// Filter Settings ////////// +static int flt_set[3] = {10, 9, 10}; + +__inline void +memshl (register int *pA, register int *pB) { + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA = *pB; +} + +__inline void +hybrid_filter (fltst *fs, int *in) { + register int *pA = fs->dl; + register int *pB = fs->qm; + register int *pM = fs->dx; + register int sum = fs->round; + + if (!fs->error) { + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; + sum += *pA++ * *pB, pB++; pM += 8; + } else if (fs->error < 0) { + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + sum += *pA++ * (*pB -= *pM++), pB++; + } else { + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + sum += *pA++ * (*pB += *pM++), pB++; + } + + *(pM-0) = ((*(pA-1) >> 30) | 1) << 2; + *(pM-1) = ((*(pA-2) >> 30) | 1) << 1; + *(pM-2) = ((*(pA-3) >> 30) | 1) << 1; + *(pM-3) = ((*(pA-4) >> 30) | 1); + + fs->error = *in; + *in += (sum >> fs->shift); + *pA = *in; + + *(pA-1) = *(pA-0) - *(pA-1); + *(pA-2) = *(pA-1) - *(pA-2); + *(pA-3) = *(pA-2) - *(pA-3); + + memshl (fs->dl, fs->dl + 1); + memshl (fs->dx, fs->dx + 1); +} + +void +filter_init (fltst *fs, int shift) { + memset (fs, 0, sizeof(fltst)); + fs->shift = shift; + fs->round = 1 << (shift - 1); +} + +#endif /* FILTERS_H */ + Property changes on: apps/codecs/libtta/filters.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/tta.c =================================================================== --- apps/codecs/tta.c (revision 0) +++ apps/codecs/tta.c (revision 0) @@ -0,0 +1,286 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: + * + * Copyright (C) 2009 Michael Giacomelli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "codeclib.h" +#include "libtta/ttalib.h" +//#include "libtta/ttadec.h" +//#include "libtta/crc32.h" + +#define BUFFER_SIZE 1024*17 +static char pcm_buffer[32000]; //TODO: figure out the correct value + +CODEC_HEADER +#if 0 +long open_tta_file (tta_hdr *ttahdr, tta_info *info, unsigned long data_offset) { + //FILE *infile; + + unsigned long checksum; + + // clear the memory + memset (info, 0, sizeof(tta_info)); + + //info->HANDLE = infile = fopen(filename, "rb"); + //if (!infile) return OPEN_ERROR; + + // skip id3v2 header - worry about this later, our file doesn't have one + /*if (!data_offset) { + data_offset = get_id3v2_tag (info); + //data_offset = skip_id3v2_header(infile); + get_id3v1_tag (info); + if (data_offset < 0) return -1; + } else fseek (infile, data_offset, SEEK_SET); + */ + // read TTA header + /*if (fread (&ttahdr, 1, sizeof (ttahdr), infile) == 0) { + fclose (infile); + info->STATE = READ_ERROR; + return -1; + }*/ + ttahdr= + + // check for TTA3 signature + if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) { + fclose (infile); + info->STATE = FORMAT_ERROR; + return -1; + } + + ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32); + checksum = crc32((unsigned char *) &ttahdr, + sizeof(tta_hdr) - sizeof(long)); + if (checksum != ttahdr.CRC32) { + fclose (infile); + 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)) { + fclose (infile); + info->STATE = FORMAT_ERROR; + return FORMAT_ERROR; + } + + // fill the File Info + info->HANDLE = infile; + 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 = (long) (FRAME_TIME * ttahdr.SampleRate); + info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate; + info->DATAPOS = data_offset; + + + return 0; +} + +#endif +/* this is the codec entry point */ +enum codec_status codec_main(void) +{ + uint8_t* buf, buf2; + size_t bufsize; + tta_hdr ttahdr; + int32_t crc; + tta_info info; // currently playing file info + int i, lastlen, fframes,st_size; + int bufadvance, len; + + + DEBUGF("in tta at buffer offset! %x\n",ci->curpos); +next_track: + if (codec_init()) { + DEBUGF("codec init failed\n"); + return CODEC_ERROR; + } + + while (!*ci->taginfo_ready && !ci->stop_codec) + ci->sleep(1); + + //codec_set_replaygain(ci->id3); + + /* Init Codec for Track */ + memset (&info, 0, sizeof(tta_info)); + + /* Read in 22 bytes for the header and transfer into the struct*/ + DEBUGF("request buffer 1\n"); + buf=ci->request_buffer(&bufsize, 22); + memcpy(&ttahdr,buf, 22); + ci->advance_buffer(22); + DEBUGF("request buffer 2\n"); + //buf2=buf; + /*for(i=0; i<10; i++){ + DEBUGF("%x\n", *buf++); + } + */ + /* + for(i=0; i<3; i++){ + DEBUGF("%d\n", *((int32_t *)buf)); + } + */ + + + DEBUGF("sample rate: %d\n", (int32_t)ENDSWAP_INT32(ttahdr.SampleRate)); + + + // check for TTA3 signature + if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) { + + + return CODEC_ERROR; + } + ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32); + + crc = crc32((unsigned char *) &ttahdr, sizeof(tta_hdr) - sizeof(int32_t)); + if (crc != ttahdr.CRC32) { + DEBUGF("checksum fail!\nWas %x, expected %x", crc, ttahdr.CRC32); + return CODEC_ERROR; + } + + 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); + + + 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 = (long) (FRAME_TIME * ttahdr.SampleRate); + info.LENGTH = ttahdr.DataLength / ttahdr.SampleRate; + //info.DATAPOS = data_offset; //used for skipping id3v2 tags, worry about it later + + /*borrow the logic from player_init to figure out how big the seek table is*/ + lastlen = info.DATALENGTH % info.FRAMELEN; + fframes = info.DATALENGTH / info.FRAMELEN + (lastlen ? 1 : 0); + st_size = (fframes + 1) * sizeof(int); + + /*get the seek table from the buffer*/ + buf=ci->request_buffer(&bufsize, st_size); + if(bufsizeadvance_buffer(bufsize); + DEBUGF("going in get_samples at offset: %x\n", ci->curpos); + + /* Make use of 44.1khz */ + ci->configure(DSP_SET_FREQUENCY, 44100); + /* Sample depth is 16 bit little endian */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); + /* Stereo or Mono output ? */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); + + /* reset eleapsed */ + ci->set_elapsed(0); + + /* The main decoder loop */ + + while (1) + { + + ci->yield(); + if (ci->stop_codec || ci->new_track) + break; + + if (ci->seek_time) { + /* New time is ready in ci->seek_time */ + /* absolute position in ms */ + + /* seek to pos */ + + /* update elapsed */ + ci->set_elapsed(ci->seek_time); + + /* seek ready */ + ci->seek_complete(); + } + + /* Generate a buffer full of Audio */ + /* Request pointer to file buffer which can be used to read + amount of data. tells the buffer system + how much data it should try to allocate. If is 0, + end of file is reached. */ + //void* (*request_buffer)(size_t *realsize, size_t reqsize); + + buf=ci->request_buffer(&bufsize, BUFFER_SIZE); + len=get_samples(pcm_buffer, buf, bufsize, &bufadvance); + if(len<0){ + DEBUGF("decode failed"); + return CODEC_ERROR; + } + DEBUGF("completed call with return: %x\n", len); + exit(0); + + + //for(i=0; i<15; i++){ + // DEBUGF("%x\n", *buf++); + //} + + + + /* Insert a buffer full of samples */ + ci->pcmbuf_insert(pcm_buffer, NULL, len); + ci->advance_buffer(bufadvance); + + /* update elapsed in ms */ + //ci->set_elapsed(current_Pos); + + //if( EndOfFile ) + // break; + } + + if (ci->request_next_track()) + goto next_track; + + return CODEC_OK; +} \ No newline at end of file Property changes on: apps/codecs/tta.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/codecs.make =================================================================== --- apps/codecs/codecs.make (revision 20206) +++ apps/codecs/codecs.make (working copy) @@ -33,6 +33,7 @@ include $(APPSDIR)/codecs/libtremor/libtremor.make include $(APPSDIR)/codecs/libwavpack/libwavpack.make include $(APPSDIR)/codecs/libwma/libwma.make +include $(APPSDIR)/codecs/libtta/libtta.make # compile flags for codecs CODECFLAGS = $(CFLAGS) -I$(APPSDIR)/codecs -I$(APPSDIR)/codecs/lib \ @@ -73,6 +74,7 @@ $(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a $(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a $(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a +$(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a $(CODECS): $(CODECLIB) # this must be last in codec dependency list Index: apps/codecs/SOURCES =================================================================== --- apps/codecs/SOURCES (revision 20206) +++ apps/codecs/SOURCES (working copy) @@ -6,6 +6,7 @@ wav.c a52.c wavpack.c +tta.c #ifndef RB_PROFILE alac.c #endif Index: apps/codecs/libtremor/info.c =================================================================== --- apps/codecs/libtremor/info.c (revision 20206) +++ apps/codecs/libtremor/info.c (working copy) @@ -138,34 +138,11 @@ } static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ - int i; int vendorlen=oggpack_read(opb,32); if(vendorlen<0)goto err_out; vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); _v_readstring(opb,vc->vendor,vendorlen); - vc->comments=oggpack_read(opb,32); - if(vc->comments<0)goto err_out; - vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); - vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); - - for(i=0;icomments;i++){ - int len=oggpack_read(opb,32); - if(len<0)goto err_out; - vc->comment_lengths[i]=len; - if(len>10000){ /*truncate long comments rather then seg faulting*/ - vc->user_comments[i]=(char *)_ogg_calloc(10001,1); - _v_readstring(opb,vc->user_comments[i],10000); - /*just to be neat, consumed and discard the rest of the comment*/ - len-=10000; - while(len--) - oggpack_read(opb,8); - }else{ - vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); - _v_readstring(opb,vc->user_comments[i],len); - } - } - if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ - + vc->comments=0; return(0); err_out: vorbis_comment_clear(vc);