summaryrefslogtreecommitdiffstats
path: root/lib/rbcodec/codecs/asap.c
blob: 8d1eb447cc198d4d9500652084769b41fcb5ad05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2008 Dominik Wenger
 *
 * 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 "libasap/asap.h"

CODEC_HEADER

#define CHUNK_SIZE (1024*2)

static byte samples[CHUNK_SIZE] IBSS_ATTR;   /* The sample buffer */
static ASAP_State asap IBSS_ATTR;         /* asap codec state */

/* this is the codec entry point */
enum codec_status codec_main(enum codec_entry_call_reason reason)
{
    /* Nothing to do */
    return CODEC_OK;
    (void)reason;
}

/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int n_bytes;
    int song;
    int duration;
    char* module;
    int bytesPerSample =2;
    intptr_t param;
    
    if (codec_init()) {
        DEBUGF("codec init failed\n");
        return CODEC_ERROR;
    }

    param = ci->id3->elapsed;

    codec_set_replaygain(ci->id3);
        
    int bytes_done =0;   
    size_t filesize;
    ci->seek_buffer(0);
    module = ci->request_buffer(&filesize, ci->filesize);
    if (!module || (size_t)filesize < (size_t)ci->filesize) 
    {
        DEBUGF("loading error\n");
        return CODEC_ERROR;
    }

    /*Init ASAP */
    if (!ASAP_Load(&asap, ci->id3->path, module, filesize))
    {
        DEBUGF("%s: format not supported",ci->id3->path);
        return CODEC_ERROR;
    }  
    
      /* 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 ? */
    if(asap.module_info->channels ==1)
    {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
        bytesPerSample = 2;
    }
    else
    {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
        bytesPerSample = 4; 
    }    

    song = asap.module_info->default_song;
    duration = asap.module_info->durations[song];
    if (duration < 0)
        duration = 180 * 1000;
    
    /* set id3 length, because metadata parse might not have done it */
    ci->id3->length = duration;
    
    ASAP_PlaySong(&asap, song, duration);
    ASAP_MutePokeyChannels(&asap, 0);
    
    if (param)
        goto resume_start;

    ci->set_elapsed(0);

    /* The main decoder loop */    
    while (1) {
        long action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
        resume_start:
            /* New time is ready in param */

            /* seek to pos */
            ASAP_Seek(&asap,param);
            /* update bytes_done */
            bytes_done = param*44.1*2;    
            /* update elapsed */
            ci->set_elapsed((bytes_done / 2) / 44.1);
            /* seek ready */    
            ci->seek_complete();            
        }
        
        /* Generate a buffer full of Audio */
        #ifdef ROCKBOX_LITTLE_ENDIAN
        n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_LE);
        #else
        n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_BE);
        #endif
        
        ci->pcmbuf_insert(samples, NULL, n_bytes /bytesPerSample);
        
        bytes_done += n_bytes;
        ci->set_elapsed((bytes_done / 2) / 44.1);
        
        if(n_bytes != sizeof(samples))
            break;
    }
 
    return CODEC_OK;    
}