blob: c75f2b0a5714e7b885c68965bf73ad995ed64ac4 [file] [log] [blame]
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +00001/***************************************************************************
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 */
Michael Sevakisc537d592011-04-27 03:08:23 +000037enum codec_status codec_main(enum codec_entry_call_reason reason)
38{
39 if (reason == CODEC_LOAD) {
40 /* Generic codec initialisation */
41 ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
42 }
43
44 return CODEC_OK;
45}
46
47/* this is called for each file to process */
48enum codec_status codec_run(void)
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000049{
50 tta_info info;
Yoshihisa Uchida32794a92010-05-14 11:08:56 +000051 unsigned int decodedsamples;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000052 int endofstream;
53 int new_pos = 0;
54 int sample_count;
Michael Sevakisc537d592011-04-27 03:08:23 +000055 intptr_t param;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000056
57 if (codec_init())
58 {
59 DEBUGF("codec_init() error\n");
Michael Sevakisc537d592011-04-27 03:08:23 +000060 return CODEC_ERROR;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000061 }
62
Michael Sevakisc537d592011-04-27 03:08:23 +000063 ci->seek_buffer(0);
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000064
Yoshihisa Uchida32794a92010-05-14 11:08:56 +000065 if (set_tta_info(&info) < 0 || player_init(&info) < 0)
Michael Sevakisc537d592011-04-27 03:08:23 +000066 return CODEC_ERROR;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000067
68 codec_set_replaygain(ci->id3);
69
70 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
71 if (info.NCH == 2) {
72 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
73 } else if (info.NCH == 1) {
74 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
75 } else {
76 DEBUGF("CODEC_ERROR: more than 2 channels\n");
Michael Sevakisc537d592011-04-27 03:08:23 +000077 player_stop();
78 return CODEC_ERROR;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000079 }
80
81 /* The main decoder loop */
Yoshihisa Uchida32794a92010-05-14 11:08:56 +000082 decodedsamples = 0;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000083 endofstream = 0;
84
85 if (ci->id3->offset > 0)
86 {
87 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
88 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
89 if (new_pos >= 0)
90 decodedsamples = new_pos;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000091 }
92
93 while (!endofstream)
94 {
Michael Sevakisc537d592011-04-27 03:08:23 +000095 enum codec_command_action action = ci->get_command(&param);
96
97 if (action == CODEC_ACTION_HALT)
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +000098 break;
99
Michael Sevakisc537d592011-04-27 03:08:23 +0000100 if (action == CODEC_ACTION_SEEK_TIME)
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000101 {
Michael Sevakisc537d592011-04-27 03:08:23 +0000102 new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME);
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000103 if (new_pos >= 0)
104 {
105 decodedsamples = new_pos;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000106 }
Michael Sevakisc537d592011-04-27 03:08:23 +0000107
108 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
109 ci->seek_complete();
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000110 }
111
112 sample_count = get_samples(samples);
113 if (sample_count < 0)
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000114 break;
Michael Sevakisc537d592011-04-27 03:08:23 +0000115
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000116 ci->pcmbuf_insert(samples, NULL, sample_count);
117 decodedsamples += sample_count;
118 if (decodedsamples >= info.DATALENGTH)
119 endofstream = 1;
120 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
121 }
Michael Sevakis85e40252011-02-20 15:27:10 +0000122
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000123 player_stop();
Michael Sevakisc537d592011-04-27 03:08:23 +0000124 return CODEC_OK;
Yoshihisa Uchida0f5c6d42010-05-13 12:40:09 +0000125}