Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 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 | |
| 25 | CODEC_HEADER |
| 26 | |
| 27 | /* |
| 28 | * TTA (True Audio) codec: |
| 29 | * |
| 30 | * References |
| 31 | * [1] TRUE AUDIO CODEC SOFTWARE http://true-audio.com/ |
| 32 | */ |
| 33 | |
| 34 | static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; |
| 35 | |
| 36 | /* this is the codec entry point */ |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 37 | enum 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 */ |
| 48 | enum codec_status codec_run(void) |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 49 | { |
| 50 | tta_info info; |
Yoshihisa Uchida | 32794a9 | 2010-05-14 11:08:56 +0000 | [diff] [blame] | 51 | unsigned int decodedsamples; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 52 | int endofstream; |
| 53 | int new_pos = 0; |
| 54 | int sample_count; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 55 | intptr_t param; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 56 | |
| 57 | if (codec_init()) |
| 58 | { |
| 59 | DEBUGF("codec_init() error\n"); |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 60 | return CODEC_ERROR; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 61 | } |
| 62 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 63 | ci->seek_buffer(0); |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 64 | |
Yoshihisa Uchida | 32794a9 | 2010-05-14 11:08:56 +0000 | [diff] [blame] | 65 | if (set_tta_info(&info) < 0 || player_init(&info) < 0) |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 66 | return CODEC_ERROR; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 67 | |
| 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 Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 77 | player_stop(); |
| 78 | return CODEC_ERROR; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | /* The main decoder loop */ |
Yoshihisa Uchida | 32794a9 | 2010-05-14 11:08:56 +0000 | [diff] [blame] | 82 | decodedsamples = 0; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 83 | 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 Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | while (!endofstream) |
| 94 | { |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 95 | enum codec_command_action action = ci->get_command(¶m); |
| 96 | |
| 97 | if (action == CODEC_ACTION_HALT) |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 98 | break; |
| 99 | |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 100 | if (action == CODEC_ACTION_SEEK_TIME) |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 101 | { |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 102 | new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME); |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 103 | if (new_pos >= 0) |
| 104 | { |
| 105 | decodedsamples = new_pos; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 106 | } |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 107 | |
| 108 | ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); |
| 109 | ci->seek_complete(); |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | sample_count = get_samples(samples); |
| 113 | if (sample_count < 0) |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 114 | break; |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 115 | |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 116 | 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 Sevakis | 85e4025 | 2011-02-20 15:27:10 +0000 | [diff] [blame] | 122 | |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 123 | player_stop(); |
Michael Sevakis | c537d59 | 2011-04-27 03:08:23 +0000 | [diff] [blame^] | 124 | return CODEC_OK; |
Yoshihisa Uchida | 0f5c6d4 | 2010-05-13 12:40:09 +0000 | [diff] [blame] | 125 | } |