summaryrefslogtreecommitdiff
path: root/apps/codecs/tta.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/tta.c')
-rw-r--r--apps/codecs/tta.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/apps/codecs/tta.c b/apps/codecs/tta.c
new file mode 100644
index 0000000000..541dc2b7ef
--- /dev/null
+++ b/apps/codecs/tta.c
@@ -0,0 +1,132 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Yoshihisa Uchida
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "codeclib.h"
23#include "codecs/libtta/ttalib.h"
24
25CODEC_HEADER
26
27/*
28 * TTA (True Audio) codec:
29 *
30 * References
31 * [1] TRUE AUDIO CODEC SOFTWARE http://true-audio.com/
32 */
33
34static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR;
35
36/* this is the codec entry point */
37enum codec_status codec_main(void)
38{
39 tta_info info;
40 int status = CODEC_OK;
41 unsigned int decodedsamples = 0;
42 int endofstream;
43 int new_pos = 0;
44 int sample_count;
45
46 /* Generic codec initialisation */
47 ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
48
49 if (codec_init())
50 {
51 DEBUGF("codec_init() error\n");
52 status = CODEC_ERROR;
53 goto exit;
54 }
55
56next_track:
57 while (!*ci->taginfo_ready && !ci->stop_codec)
58 ci->sleep(1);
59
60 if (set_tta_info(&info) < 0)
61 {
62 status = CODEC_ERROR;
63 goto exit;
64 }
65 if (player_init(&info) < 0)
66 {
67 status = CODEC_ERROR;
68 goto exit;
69 }
70
71 codec_set_replaygain(ci->id3);
72
73 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
74 if (info.NCH == 2) {
75 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
76 } else if (info.NCH == 1) {
77 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
78 } else {
79 DEBUGF("CODEC_ERROR: more than 2 channels\n");
80 status = CODEC_ERROR;
81 goto done;
82 }
83
84 /* The main decoder loop */
85 endofstream = 0;
86
87 if (ci->id3->offset > 0)
88 {
89 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
90 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
91 if (new_pos >= 0)
92 decodedsamples = new_pos;
93 ci->seek_complete();
94 }
95
96 while (!endofstream)
97 {
98 ci->yield();
99 if (ci->stop_codec || ci->new_track)
100 break;
101
102 if (ci->seek_time)
103 {
104 new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME);
105 if (new_pos >= 0)
106 {
107 decodedsamples = new_pos;
108 ci->seek_complete();
109 }
110 }
111
112 sample_count = get_samples(samples);
113 if (sample_count < 0)
114 {
115 status = CODEC_ERROR;
116 break;
117 }
118 ci->pcmbuf_insert(samples, NULL, sample_count);
119 decodedsamples += sample_count;
120 if (decodedsamples >= info.DATALENGTH)
121 endofstream = 1;
122 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
123 }
124 status = CODEC_OK;
125done:
126 player_stop();
127 if (ci->request_next_track())
128 goto next_track;
129
130exit:
131 return status;
132}