コード例 #1
0
ファイル: a52.c プロジェクト: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    size_t n;
    unsigned char *filebuf;
    int sample_loc;
    intptr_t param;

    if (codec_init())
        return CODEC_ERROR;

    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);
    
    /* Intialise the A52 decoder and check for success */
    state = a52_init(0);

    samplesdone = 0;

    /* The main decoding loop */
    if (ci->id3->offset) {
        if (ci->seek_buffer(ci->id3->offset)) {
            samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
                A52_SAMPLESPERFRAME;
            ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
        }
    }
    else {
        ci->seek_buffer(ci->id3->first_frame_offset);
        ci->set_elapsed(0);
    }

    while (1) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            sample_loc = param/1000 * ci->id3->frequency;

            if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
                samplesdone = sample_loc;
                ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
            }
            ci->seek_complete();
        }

        filebuf = ci->request_buffer(&n, BUFFER_SIZE);

        if (n == 0) /* End of Stream */
            break;
  
        a52_decode_data(filebuf, filebuf + n);
        ci->advance_buffer(n);
    }

    return CODEC_OK;
}
コード例 #2
0
ファイル: vorbis.c プロジェクト: BurntBrunch/rockbox-fft
/* This sets the DSP parameters based on the current logical bitstream
 * (sampling rate, number of channels, etc).
 */
static bool vorbis_set_codec_parameters(OggVorbis_File *vf)
{
    vorbis_info *vi;

    vi = ov_info(vf, -1);

    if (vi == NULL) {
        return false;
    }

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    if (vi->channels == 2) {
          ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    } else if (vi->channels == 1) {
          ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    }

    return true;
}
コード例 #3
0
ファイル: alac.c プロジェクト: a-martinez/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    size_t n;
    demux_res_t demux_res;
    stream_t input_stream;
    uint32_t samplesdone;
    uint32_t elapsedtime;
    uint32_t sample_duration;
    uint32_t sample_byte_size;
    int samplesdecoded;
    unsigned int i;
    unsigned char* buffer;
    alac_file alac;
    int retval;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);

next_track:

    if (codec_init()) {
        LOGF("ALAC: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    stream_create(&input_stream,ci);

    /* Read from ci->id3->offset before calling qtmovie_read. */
    samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) /
                             (ci->id3->bitrate*128));

    /* if qtmovie_read returns successfully, the stream is up to
     * the movie data, which can be used directly by the decoder */
    if (!qtmovie_read(&input_stream, &demux_res)) {
        LOGF("ALAC: Error initialising file\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* initialise the sound converter */
    create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac);
    alac_set_info(&alac, demux_res.codecdata);

    /* Set i for first frame, seek to desired sample position for resuming. */
    i=0;
    if (samplesdone > 0) {
        if (alac_seek(&demux_res, &input_stream, samplesdone,
                      &samplesdone, (int*) &i)) {
            elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
            ci->set_elapsed(elapsedtime);
        } else {
            samplesdone = 0;
        }
    }

    /* The main decoding loop */
    while (i < demux_res.num_sample_byte_sizes) {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            break;
        }

        /* Deal with any pending seek requests */
        if (ci->seek_time) {
            if (alac_seek(&demux_res, &input_stream,
                          ((ci->seek_time-1)/10) * (ci->id3->frequency/100),
                          &samplesdone, (int *)&i)) {
                elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
                ci->set_elapsed(elapsedtime);
            }
            ci->seek_complete();
        }

        /* Lookup the length (in samples and bytes) of block i */
        if (!get_sample_info(&demux_res, i, &sample_duration,
                             &sample_byte_size)) {
            LOGF("ALAC: Error in get_sample_info\n");
            retval = CODEC_ERROR;
            goto done;
        }

        /* Request the required number of bytes from the input buffer */

        buffer=ci->request_buffer(&n,sample_byte_size);
        if (n!=sample_byte_size) {
            retval = CODEC_ERROR;
            goto done;
        }

        /* Decode one block - returned samples will be host-endian */
        ci->yield();
        samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);

        /* Advance codec buffer n bytes */
        ci->advance_buffer(n);

        /* Output the audio */
        ci->yield();
        ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);

        /* Update the elapsed-time indicator */
        samplesdone+=sample_duration;
        elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
        ci->set_elapsed(elapsedtime);

        i++;
    }
    retval = CODEC_OK;

done:
    LOGF("ALAC: Decoded %ld samples\n",samplesdone);

    if (ci->request_next_track())
        goto next_track;

exit:
    return retval;
}
コード例 #4
0
ファイル: speex.c プロジェクト: lyzkov/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;

    SpeexBits bits;
    int eof = 0;
    spx_ogg_sync_state oy;
    spx_ogg_page og;
    spx_ogg_packet op;
    spx_ogg_stream_state os;
    spx_int64_t page_granule = 0;
    spx_int64_t cur_granule = 0;
    int enh_enabled = 1;
    int nframes = 2;
    int eos = 0;
    SpeexStereoState *stereo;
    int channels = -1;
    int samplerate = ci->id3->frequency;
    int extra_headers = 0;
    int stream_init = 0;
    /* rockbox: comment 'set but unused' variables
    int page_nb_packets;
    */
    int frame_size;
    int packet_count = 0;
    int lookahead;
    int headerssize = 0;
    unsigned long strtoffset = ci->id3->offset;
    void *st = NULL;
    int j = 0;
    intptr_t param;

    memset(&bits, 0, sizeof(bits));
    memset(&oy, 0, sizeof(oy));

    /* Ogg handling still uses mallocs, so reset the malloc buffer per track */
    if (codec_init()) {
        goto exit;
    }

    ci->seek_buffer(0);
    ci->set_elapsed(0);

    stereo = speex_stereo_state_init();
    spx_ogg_sync_init(&oy);
    spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE);

    codec_set_replaygain(ci->id3);

    eof = 0;
    while (!eof) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /*seek (seeks to the page before the position) */
        if (action == CODEC_ACTION_SEEK_TIME) {
            if(samplerate!=0&&packet_count>1){
                LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
                     ((spx_int64_t)param/1000) *
                     (spx_int64_t)samplerate,
                     page_granule, param,
                     (page_granule/samplerate)*1000, samplerate);

                speex_seek_page_granule(((spx_int64_t)param/1000) *
                                        (spx_int64_t)samplerate,
                                        page_granule, &oy, headerssize);
            }

            ci->set_elapsed(param);
            ci->seek_complete();
        }

next_page:
        /*Get the ogg buffer for writing*/
        if(get_more_data(&oy)<1){/*read error*/
            goto done;
        }

        /* Loop for all complete pages we got (most likely only one) */
        while (spx_ogg_sync_pageout(&oy, &og) == 1) {
            int packet_no;
            if (stream_init == 0) {
                spx_ogg_stream_init(&os, spx_ogg_page_serialno(&og));
                stream_init = 1;
            }

            /* Add page to the bitstream */
            spx_ogg_stream_pagein(&os, &og);

            page_granule = spx_ogg_page_granulepos(&og);
            /* page_nb_packets = spx_ogg_page_packets(&og); */

            cur_granule = page_granule;

            /* Extract all available packets */
            packet_no=0;

            while (!eos && spx_ogg_stream_packetout(&os, &op)==1){
                /* If first packet, process as Speex header */
                if (packet_count==0){
                    st = process_header(&op, enh_enabled, &frame_size,
                                         &samplerate, &nframes, &channels,
                                         stereo, &extra_headers);

                    speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
                    if (!nframes)
                        nframes=1;

                    if (!st){
                        goto done;
                    }

                    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
                    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
                    if (channels == 2) {
                        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
                    } else if (channels == 1) {
                        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
                    }

                    /* Speex header in its own page, add the whole page
                       headersize */
                    headerssize += og.header_len+og.body_len;

                } else if (packet_count<=1+extra_headers){
                    /* add packet to headersize */
                    headerssize += op.bytes;

                    /* Ignore extra headers */
                } else {
                    if (packet_count <= 2+extra_headers) {
                        if (strtoffset) {
                            ci->seek_buffer(strtoffset);
                            spx_ogg_sync_reset(&oy);
                            packet_count++;
                            goto next_page;
                        }
                    }
                    packet_no++;

                    if (op.e_o_s) /* End of stream condition */
                        eos=1;

                    /* Set Speex bitstream to point to Ogg packet */
                    speex_bits_set_bit_buffer(&bits, (char *)op.packet,
                                                     op.bytes);
                    for (j = 0; j != nframes; j++){
                        int ret;

                        /* Decode frame */
                        ret = speex_decode_int(st, &bits, output);

                        if (ret == -1)
                            break;

                        if (ret == -2)
                            break;

                        if (speex_bits_remaining(&bits) < 0)
                            break;

                        if (channels == 2)
                            speex_decode_stereo_int(output, frame_size, stereo);

                        if (frame_size > 0) {
                            spx_int16_t *frame_start = output + lookahead;

                            if (channels == 2)
                                frame_start += lookahead;
                            ci->pcmbuf_insert(frame_start, NULL,
                                              frame_size - lookahead);
                            lookahead = 0;
                            /* 2 bytes/sample */
                            cur_granule += frame_size / 2;

                            ci->set_offset((long) ci->curpos);

                            ci->set_elapsed((samplerate == 0) ? 0 :
                                             cur_granule * 1000 / samplerate);
                         }
                    }
                }
                packet_count++;
            }
        }
    }

    error = CODEC_OK;
done:
    /* Clean things up for the next track */
    speex_bits_destroy(&bits);

    if (st)
        speex_decoder_destroy(st);

    if (stream_init)
       spx_ogg_stream_destroy(&os);

    spx_ogg_sync_destroy(&oy);

exit:
    return error;
}
コード例 #5
0
ファイル: atrac3_oma.c プロジェクト: Rockbox/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    static size_t buff_size;
    int datasize, res, frame_counter, total_frames, seek_frame_offset;
    uint8_t *bit_buffer;
    int elapsed = 0;
    size_t resume_offset;
    intptr_t param;
    long action;

    if (codec_init()) {
        DEBUGF("codec init failed\n");
        return CODEC_ERROR;
    }

    action = CODEC_ACTION_NULL;
    param = ci->id3->elapsed;
    resume_offset = ci->id3->offset;

    codec_set_replaygain(ci->id3);
    ci->memset(&q,0,sizeof(ATRAC3Context));
 
    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
    ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ?
        STEREO_MONO : STEREO_NONINTERLEAVED);

    ci->seek_buffer(0);

    res = atrac3_decode_init(&q, ci->id3);
    if(res < 0) {
        DEBUGF("failed to initialize OMA atrac decoder\n");
        return CODEC_ERROR;
    }

    total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE;
    frame_counter = 0;
    
    /* check for a mid-track resume and force a seek time accordingly */
    if (resume_offset) {
        resume_offset -= MIN(resume_offset, ci->id3->first_frame_offset);
        /* calculate resume_offset in frames */
        param = (resume_offset/FRAMESIZE) * ((FRAMESIZE * 8)/BITRATE);
    }

    if ((unsigned long)param) {
        action = CODEC_ACTION_SEEK_TIME;
    }
    else {
        ci->set_elapsed(0);
        ci->seek_buffer(ci->id3->first_frame_offset);
    }

    /* The main decoder loop */  
    while(frame_counter < total_frames)
    {
        if (action == CODEC_ACTION_NULL)
            action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            /* Do not allow seeking beyond the file's length */
            if ((unsigned long) param > ci->id3->length) {
                ci->set_elapsed(ci->id3->length);
                ci->seek_complete();
                break;
            }       

            /* Seek to the start of the track */
            if (param == 0) {
                elapsed = 0;
                ci->set_elapsed(0);
                ci->seek_buffer(ci->id3->first_frame_offset);
                ci->seek_complete();
                action = CODEC_ACTION_NULL;
                continue;           
            }                                                                

            seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE);
            frame_counter = seek_frame_offset;
            ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
            elapsed = param;
            ci->set_elapsed(elapsed);
            ci->seek_complete(); 
        }

        action = CODEC_ACTION_NULL;

        bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);

        res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);

        if(res != (int)FRAMESIZE) {
            DEBUGF("codec error\n");
            return CODEC_ERROR;
        }

        if(datasize)
            ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024,
                              q.samples_per_frame / ci->id3->channels);

        elapsed += (FRAMESIZE * 8) / BITRATE;
        ci->set_elapsed(elapsed);

        ci->advance_buffer(FRAMESIZE);
        frame_counter++;
    }

    return CODEC_OK;    
}
コード例 #6
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    WavpackContext *wpc;
    char error [80];
    /* rockbox: comment 'set but unused' variables
    int bps;
    */
    int nchans, sr_100;
    intptr_t param;

    if (codec_init())
        return CODEC_ERROR;

    ci->seek_buffer (ci->id3->offset);

    /* Create a decoder instance */
    wpc = WavpackOpenFileInput (read_callback, error);

    if (!wpc)
        return CODEC_ERROR;

    ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc));
    codec_set_replaygain(ci->id3);
    /* bps = WavpackGetBytesPerSample (wpc); */
    nchans = WavpackGetReducedChannels (wpc);
    ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO);
    sr_100 = ci->id3->frequency / 100;

    ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);

    /* The main decoder loop */

    while (1) {
        int32_t nsamples;
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10;
            int n, d, skip;

            if (param > curpos_ms) {
                n = param - curpos_ms;
                d = ci->id3->length - curpos_ms;
                skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d);
                ci->seek_buffer (ci->curpos + skip);
            }
            else if (curpos_ms != 0) {
                n = curpos_ms - param;
                d = curpos_ms;
                skip = (int)((int64_t) ci->curpos * n / d);
                ci->seek_buffer (ci->curpos - skip);
            }

            wpc = WavpackOpenFileInput (read_callback, error);
            if (!wpc)
            {
                ci->seek_complete();
                break;
            }

            ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
            ci->seek_complete();
        }

        nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans);  

        if (!nsamples)
            break;

        ci->pcmbuf_insert (temp_buffer, NULL, nsamples);
        ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
    }

    return CODEC_OK;
}
コード例 #7
0
ファイル: alac.c プロジェクト: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    size_t n;
    demux_res_t demux_res;
    stream_t input_stream;
    uint32_t samplesdone;
    uint32_t elapsedtime = 0;
    int samplesdecoded;
    unsigned int i;
    unsigned char* buffer;
    alac_file alac;
    intptr_t param;

    /* Clean and initialize decoder structures */
    memset(&demux_res , 0, sizeof(demux_res));
    if (codec_init()) {
        LOGF("ALAC: Error initialising codec\n");
        return CODEC_ERROR;
    }

    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    ci->seek_buffer(0);

    stream_create(&input_stream,ci);

    /* Read from ci->id3->offset before calling qtmovie_read. */
    samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) /  
                  (ci->id3->bitrate*128));
  
    /* if qtmovie_read returns successfully, the stream is up to
     * the movie data, which can be used directly by the decoder */
    if (!qtmovie_read(&input_stream, &demux_res)) {
        LOGF("ALAC: Error initialising file\n");
        return CODEC_ERROR;
    }

    /* initialise the sound converter */
    alac_set_info(&alac, demux_res.codecdata);
  
    /* Set i for first frame, seek to desired sample position for resuming. */
    i=0;
    if (samplesdone > 0) {
        if (m4a_seek(&demux_res, &input_stream, samplesdone,
                      &samplesdone, (int*) &i)) {
            elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
            ci->set_elapsed(elapsedtime);
        } else {
            samplesdone = 0;
        }
    }

    ci->set_elapsed(elapsedtime);

    /* The main decoding loop */
    while (i < demux_res.num_sample_byte_sizes) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {
            if (m4a_seek(&demux_res, &input_stream,
                         (param/10) * (ci->id3->frequency/100),
                         &samplesdone, (int *)&i)) {
                elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
            }
            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }

        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);

        /* Decode one block - returned samples will be host-endian */
        samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);
        ci->yield();

        /* Advance codec buffer by amount of consumed bytes */
        ci->advance_buffer(alac.bytes_consumed);

        /* Output the audio */
        ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);

        /* Update the elapsed-time indicator */
        samplesdone+=samplesdecoded;
        elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
        ci->set_elapsed(elapsedtime);

        i++;
    }

    LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone);
    return CODEC_OK;
}
コード例 #8
0
ファイル: wmapro.c プロジェクト: ntj/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;     /* Holds the stream properties */
    size_t resume_offset;
    int res;                    /* Return values from asf_read_packet() and decode_packet() */
    uint8_t* audiobuf;          /* Pointer to the payload of one wma pro packet */
    int audiobufsize;           /* Payload size */
    int packetlength = 0;       /* Logical packet size (minus the header size) */
    int outlen = 0;             /* Number of bytes written to the output buffer */
    int pktcnt = 0;             /* Count of the packets played */
    uint8_t *data;              /* Pointer to decoder input buffer */
    int size;                   /* Size of the input frame to the decoder */

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH);


next_track:

    /* Wait for the metadata to be read */
    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    retval = CODEC_OK;

    /* Remember the resume position */
    resume_offset = ci->id3->offset;
restart_track:
    if (codec_init()) {
        LOGF("(WMA PRO) Error: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    if (decode_init(&wfx) < 0) {
        LOGF("(WMA PRO) Error: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Now advance the file position to the first frame */
    ci->seek_buffer(ci->id3->first_frame_offset);

    elapsedtime = 0;
    resume_offset = 0;

    /* The main decoding loop */

    while (pktcnt < wfx.numpackets)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }

        /* Deal with any pending seek requests */
        if (ci->seek_time) {

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1) {
                ci->seek_complete();
                goto next_track;
            }

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }

        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res);
            goto done;
        } else {
            data = audiobuf;
            size = audiobufsize;
            pktcnt++;

            /* We now loop on the packet, decoding and outputting the subframes
             * one-by-one. For more information about how wma pro structures its
             * audio frames, see libwmapro/wmaprodec.c */
            while(size > 0)
            {
                res = decode_packet(&wfx, dec, &outlen, data, size);
                if(res < 0) {
                    LOGF("(WMA PRO) Error: decode_packet returned %d", res);
                    goto done;
                }
                data += res;
                size -= res;
                if(outlen) {
                    ci->yield ();
                    outlen /= (wfx.channels);
                    ci->pcmbuf_insert(dec[0], dec[1], outlen );
                    elapsedtime += outlen*10/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                    ci->yield ();
                }
            }

        }

        /* Advance to the next logical packet */
        ci->advance_buffer(packetlength);
    }
    retval = CODEC_OK;

done:
    if (ci->request_next_track())
        goto next_track;

    return retval;
}
コード例 #9
0
ファイル: cook.c プロジェクト: claymodel/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{ 
    static size_t buff_size;
    int datasize, res, consumed, i, time_offset;
    uint8_t *bit_buffer;
    uint16_t fs,sps,h;
    uint32_t packet_count;
    int scrambling_unit_size, num_units;
    size_t resume_offset;

next_track:
    if (codec_init()) {
        DEBUGF("codec init failed\n");
        return CODEC_ERROR;
    }

    if (codec_wait_taginfo() != 0)
        goto done;

    resume_offset = ci->id3->offset;

    codec_set_replaygain(ci->id3);
    ci->memset(&rmctx,0,sizeof(RMContext));
    ci->memset(&pkt,0,sizeof(RMPacket));
    ci->memset(&q,0,sizeof(COOKContext));

    init_rm(&rmctx);
 
    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    /* cook's sample representation is 21.11
     * DSP_SET_SAMPLE_DEPTH = 11 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 26 */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 26);
    ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);

    packet_count = rmctx.nb_packets;
    rmctx.audio_framesize = rmctx.block_align;
    rmctx.block_align = rmctx.sub_packet_size;
    fs = rmctx.audio_framesize;
    sps= rmctx.block_align;
    h = rmctx.sub_packet_h;
    scrambling_unit_size = h*fs;
    
    res =cook_decode_init(&rmctx, &q);
    if(res < 0) {
        DEBUGF("failed to initialize cook decoder\n");
        return CODEC_ERROR;
    }
    
    /* check for a mid-track resume and force a seek time accordingly */
    if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
        resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
        num_units = (int)resume_offset / scrambling_unit_size;    
        /* put number of subpackets to skip in resume_offset */
        resume_offset /= (sps + PACKET_HEADER_SIZE);
        ci->seek_time =  (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);                
    }

    ci->set_elapsed(0);
    ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);

    /* The main decoder loop */  
seek_start :         
    while(packet_count)
    {  
        bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
        consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
        if(consumed < 0) {
            DEBUGF("rm_get_packet failed\n");
            return CODEC_ERROR;
        }
       
        for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
        { 
            ci->yield();
            if (ci->stop_codec || ci->new_track)
                goto done;

            if (ci->seek_time) {
                ci->set_elapsed(ci->seek_time);

                /* Do not allow seeking beyond the file's length */
                if ((unsigned) ci->seek_time > ci->id3->length) {
                    ci->seek_complete();
                    goto done;
                }       

                ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
                packet_count = rmctx.nb_packets;
                rmctx.audio_pkt_cnt = 0;
                rmctx.frame_number = 0;

                /* Seek to the start of the track */
                if (ci->seek_time == 1) {
                    ci->set_elapsed(0);
                    ci->seek_complete();
                    goto seek_start;           
                }                                                                
                num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));                    
                ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
                bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
                consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
                if(consumed < 0) {
                     DEBUGF("rm_get_packet failed\n");
                     return CODEC_ERROR;
                } 
                packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
                rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); 
                while(rmctx.audiotimestamp > (unsigned) ci->seek_time) {
                    rmctx.audio_pkt_cnt = 0;
                    ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
                    bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 
                    consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);                                                                             
                    packet_count += rmctx.audio_pkt_cnt;
                    num_units--;
                }
                time_offset = ci->seek_time - rmctx.audiotimestamp;
                i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
                ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
                ci->seek_complete(); 
            }    
            res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align);
            rmctx.frame_number++;

            /* skip the first two frames; no valid audio */
            if(rmctx.frame_number < 3) continue;

            if(res != rmctx.block_align) {
                DEBUGF("codec error\n");
                return CODEC_ERROR;
            }

            ci->pcmbuf_insert(rm_outbuf, 
                              rm_outbuf+q.samples_per_channel,
                              q.samples_per_channel);
            ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);  
        }
        packet_count -= rmctx.audio_pkt_cnt;
        rmctx.audio_pkt_cnt = 0;
        ci->advance_buffer(consumed);
    }

    done :
    if (ci->request_next_track())
        goto next_track;

    return CODEC_OK;    
}
コード例 #10
0
ファイル: wavpack.c プロジェクト: BurntBrunch/rockbox-fft
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    WavpackContext *wpc;
    char error [80];
    int bps, nchans, sr_100;
    int retval;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 28);

    next_track:

    if (codec_init()) {
        retval = CODEC_ERROR;
        goto exit;
    }

    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);
        
    /* Create a decoder instance */
    wpc = WavpackOpenFileInput (read_callback, error);

    if (!wpc) {
        retval = CODEC_ERROR;
        goto done;
    }

    ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc));
    codec_set_replaygain(ci->id3);
    bps = WavpackGetBytesPerSample (wpc);
    nchans = WavpackGetReducedChannels (wpc);
    ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO);
    sr_100 = ci->id3->frequency / 100;

    ci->set_elapsed (0);

    /* The main decoder loop */

    while (1) {
        int32_t nsamples;  

        if (ci->seek_time && ci->taginfo_ready && ci->id3->length) {
            ci->seek_time--;
            int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10;
            int n, d, skip;

            if (ci->seek_time > curpos_ms) {
                n = ci->seek_time - curpos_ms;
                d = ci->id3->length - curpos_ms;
                skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d);
                ci->seek_buffer (ci->curpos + skip);
            }
            else {
                n = curpos_ms - ci->seek_time;
                d = curpos_ms;
                skip = (int)((int64_t) ci->curpos * n / d);
                ci->seek_buffer (ci->curpos - skip);
            }

            wpc = WavpackOpenFileInput (read_callback, error);
            ci->seek_complete();

            if (!wpc)
                break;

            ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
            ci->yield ();
        }

        nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans);  

        if (!nsamples || ci->stop_codec || ci->new_track)
            break;

        ci->yield ();

        if (ci->stop_codec || ci->new_track)
            break;

        ci->pcmbuf_insert (temp_buffer, NULL, nsamples);

        ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
        ci->yield ();
    }
    retval = CODEC_OK;

done:
    if (ci->request_next_track())
        goto next_track;

exit:
    return retval;
}
コード例 #11
0
ファイル: atrac3_rm.c プロジェクト: BurntBrunch/rockbox-fft
/* this is the codec entry point */
enum codec_status codec_main(void)
{ 
    static size_t buff_size;
    int datasize, res, consumed, i, time_offset;
    uint8_t *bit_buffer;
    uint16_t fs,sps,h;
    uint32_t packet_count;
    int scrambling_unit_size, num_units, elapsed = 0;
    int playback_on = -1;
    size_t resume_offset = ci->id3->offset;

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);
    ci->memset(&rmctx,0,sizeof(RMContext));
    ci->memset(&pkt,0,sizeof(RMPacket));
    ci->memset(&q,0,sizeof(ATRAC3Context));

    init_rm(&rmctx);
 
    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
    ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
        STEREO_MONO : STEREO_NONINTERLEAVED);

    packet_count = rmctx.nb_packets;
    rmctx.audio_framesize = rmctx.block_align;
    rmctx.block_align = rmctx.sub_packet_size;
    fs = rmctx.audio_framesize;
    sps= rmctx.block_align;
    h = rmctx.sub_packet_h;
    scrambling_unit_size = h*fs;
    
    res =atrac3_decode_init(&q, &rmctx);
    if(res < 0) {
        DEBUGF("failed to initialize atrac decoder\n");
        return CODEC_ERROR;
    }

    /* check for a mid-track resume and force a seek time accordingly */
    if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
        resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
        num_units = (int)resume_offset / scrambling_unit_size;        
        /* put number of subpackets to skip in resume_offset */
        resume_offset /= (sps + PACKET_HEADER_SIZE);
        ci->seek_time =  (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);                
    }
    
    ci->set_elapsed(0);
    ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);

    /* The main decoder loop */  
seek_start :         
    while((unsigned)elapsed < rmctx.duration)
    {  
        bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
        consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
        if(consumed < 0 && playback_on != 0) {
            if(playback_on == -1) {
            /* Error only if packet-parsing failed and playback hadn't started */
                DEBUGF("rm_get_packet failed\n");
                return CODEC_ERROR;
            }
            else
                goto done;
        }

        for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
        { 
            ci->yield();
            if (ci->stop_codec || ci->new_track)
                goto done;

            if (ci->seek_time) {
                ci->set_elapsed(ci->seek_time);

                /* Do not allow seeking beyond the file's length */
                if ((unsigned) ci->seek_time > ci->id3->length) {
                    ci->seek_complete();
                    goto done;
                }       

                ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
                packet_count = rmctx.nb_packets;
                rmctx.audio_pkt_cnt = 0;
                rmctx.frame_number = 0;

                /* Seek to the start of the track */
                if (ci->seek_time == 1) {
                    ci->set_elapsed(0);
                    ci->seek_complete();
                    goto seek_start;           
                }                                                                
                num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));                    
                ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
                bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
                consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
                if(consumed < 0 && playback_on != 0) {
                    if(playback_on == -1) {
                    /* Error only if packet-parsing failed and playback hadn't started */
                        DEBUGF("rm_get_packet failed\n");
                        return CODEC_ERROR;
                    }
                    else
                        goto done;
                }

                packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
                rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); 
                while(rmctx.audiotimestamp > (unsigned) ci->seek_time) {
                    rmctx.audio_pkt_cnt = 0;
                    ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
                    bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 
                    consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);                                                                             
                    packet_count += rmctx.audio_pkt_cnt;
                    num_units--;
                }
                time_offset = ci->seek_time - rmctx.audiotimestamp;
                i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
                elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
                ci->set_elapsed(elapsed);
                ci->seek_complete(); 
            }
            if(pkt.length)    
                res = atrac3_decode_frame(&rmctx, &q, &datasize, pkt.frames[i], rmctx.block_align);
            else /* indicates that there are no remaining frames */
                goto done;

            if(res != rmctx.block_align) {
                DEBUGF("codec error\n");
                return CODEC_ERROR;
            }

            if(datasize)
                ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / rmctx.nb_channels);
            playback_on = 1;
            elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
            ci->set_elapsed(elapsed);
            rmctx.frame_number++;
        }
        packet_count -= rmctx.audio_pkt_cnt;
        rmctx.audio_pkt_cnt = 0;
        ci->advance_buffer(consumed);
    }

    done :
    if (ci->request_next_track())
        goto next_track;

    return CODEC_OK;    
}
コード例 #12
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    ShortenContext sc;
    uint32_t samplesdone;
    uint32_t elapsedtime;
    int8_t *buf;
    int consumed, res, nsamples;
    size_t bytesleft;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1);
    
next_track:
    /* Codec initialization */
    if (codec_init()) {
        LOGF("Shorten: codec_init error\n");
        return CODEC_ERROR;
    }

    while (!*ci->taginfo_ready)
        ci->yield();

    codec_set_replaygain(ci->id3);

    /* Shorten decoder initialization */
    ci->memset(&sc, 0, sizeof(ShortenContext));

    /* Skip id3v2 tags */
    ci->seek_buffer(ci->id3->first_frame_offset);

    /* Read the shorten & wave headers */
    buf = ci->request_buffer(&bytesleft, MAX_HEADER_SIZE);
    res = shorten_init(&sc, (unsigned char *)buf, bytesleft);
    if (res < 0) {
        LOGF("Shorten: shorten_init error: %d\n", res);
        return CODEC_ERROR;
    }

    ci->id3->frequency = sc.sample_rate;
    ci->configure(DSP_SWITCH_FREQUENCY, sc.sample_rate);

    if (sc.sample_rate) {
        ci->id3->length = (sc.totalsamples / sc.sample_rate) * 1000;
    } else {
        ci->id3->length = 0;
    }

    if (ci->id3->length) {
        ci->id3->bitrate = (ci->id3->filesize * 8) / ci->id3->length;
    }

    consumed = sc.gb.index/8;
    ci->advance_buffer(consumed);
    sc.bitindex = sc.gb.index - 8*consumed;

seek_start:
    /* The main decoding loop */
    ci->memset(&decoded0, 0, sizeof(int32_t)*MAX_DECODE_SIZE);
    ci->memset(&decoded1, 0, sizeof(int32_t)*MAX_DECODE_SIZE);
    ci->memset(&offset0, 0, sizeof(int32_t)*MAX_OFFSET_SIZE);
    ci->memset(&offset1, 0, sizeof(int32_t)*MAX_OFFSET_SIZE);

    samplesdone = 0;
    buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE);
    while (bytesleft) {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            break;
        }

        /* Seek to start of track */
        if (ci->seek_time == 1) {
            if (ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) {
                sc.bitindex = sc.header_bits - 8*(sc.header_bits/8);
                ci->set_elapsed(0);
                ci->seek_complete();
                goto seek_start;
            }
            ci->seek_complete();
        }

        /* Decode a frame */
        ci->memcpy(ibuf, buf, bytesleft); /* copy buf to iram */
        res = shorten_decode_frames(&sc, &nsamples, decoded0, decoded1,
                                    offset0, offset1, (unsigned char *)ibuf,
                                    bytesleft, ci->yield);
 
        if (res == FN_ERROR) {
            LOGF("Shorten: shorten_decode_frames error (%lu)\n",
                (unsigned long)samplesdone);
            break;
        } else {
            /* Insert decoded samples in pcmbuf */
            if (nsamples) {
                ci->yield();
                ci->pcmbuf_insert(decoded0 + sc.nwrap, decoded1 + sc.nwrap,
                                  nsamples);

                /* Update the elapsed-time indicator */
                samplesdone += nsamples;
                elapsedtime = (samplesdone*10) / (sc.sample_rate/100);
                ci->set_elapsed(elapsedtime);
            }

            /* End of shorten stream...go to next track */
            if (res == FN_QUIT)
                break;
        }

        consumed = sc.gb.index/8;
        ci->advance_buffer(consumed);
        buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE);
        sc.bitindex = sc.gb.index - 8*consumed;
    }

    if (ci->request_next_track())
        goto next_track;

    return CODEC_OK;
}
コード例 #13
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    int status;
    uint32_t decodedsamples;
    size_t n;
    int bufcount;
    int endofstream;
    unsigned char *buf;
    uint8_t *wavbuf;
    off_t firstblockposn;     /* position of the first block in file */
    const struct pcm_codec *codec;
    uint64_t size;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
  
next_track:
    status = CODEC_OK;

    if (codec_init()) {
        DEBUGF("codec_init() error\n");
        status = CODEC_ERROR;
        goto exit;
    }

    if (codec_wait_taginfo() != 0)
        goto done;

    codec_set_replaygain(ci->id3);
    
    /* Need to save offset for later use (cleared indirectly by advance_buffer) */
    bytesdone = ci->id3->offset;

    /* get RIFF chunk header */
    buf = ci->request_buffer(&n, 40);
    if (n < 40) {
        DEBUGF("request_buffer error\n");
        status = CODEC_ERROR;
        goto done;
    }
    if ((memcmp(buf   , WAVE64_GUID_RIFF, 16) != 0) ||
        (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0))
    {
        status = CODEC_ERROR;
        goto done;
    }

    /* advance to first WAVE chunk */
    ci->advance_buffer(40);

    firstblockposn = 40;
    ci->memset(&format, 0, sizeof(struct pcm_format));
    format.is_signed = true;
    format.is_little_endian = true;

    decodedsamples = 0;
    codec = 0;

    /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */
    while (true) {
        /* get WAVE chunk header */
        buf = ci->request_buffer(&n, 1024);
        if (n < 8) {
            DEBUGF("data chunk request_buffer error\n");
            /* no more chunks, 'data' chunk must not have been found */
            status = CODEC_ERROR;
            goto done;
        }

        /* chunkSize */
        size = get_uint64_le(buf+16) - 24;
        if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) {
            if (size < 16) {
                DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size);
                status = CODEC_ERROR;
                goto done;
            }
            /* wFormatTag */
            format.formattag=buf[24]|(buf[25]<<8);
            /* wChannels */
            format.channels=buf[26]|(buf[27]<<8);
            /* skipping dwSamplesPerSec */
            /* skipping dwAvgBytesPerSec */
            /* wBlockAlign */
            format.blockalign=buf[36]|(buf[37]<<8);
            /* wBitsPerSample */
            format.bitspersample=buf[38]|(buf[39]<<8);
            if (format.formattag != WAVE_FORMAT_PCM) {
                if (size < 18) {
                    /* this is not a fatal error with some formats,
                     * we'll see later if we can't decode it */
                    DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) "
                           "doesn't have ext. fmt descr (chunksize=%d<18).\n",
                           (unsigned int)format.formattag, (int)size);
                }
                else
                {
                    if (format.formattag != WAVE_FORMAT_EXTENSIBLE)
                        format.samplesperblock = buf[42]|(buf[43]<<8);
                    else {
                        format.size = buf[40]|(buf[41]<<8);
                        if (format.size < 22) {
                            DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
                                   "missing extension\n");
                            status = CODEC_ERROR;
                            goto done;
                        }
                        /* wValidBitsPerSample */
                        format.bitspersample = buf[42]|(buf[43]<<8);
                        /* skipping dwChannelMask (4bytes) */
                        /* SubFormat (only get the first two bytes) */
                        format.formattag = buf[48]|(buf[49]<<8);
                    }
                }
            }

            /* msadpcm specific */
            if (format.formattag == WAVE_FORMAT_ADPCM)
            {
                if (!set_msadpcm_coeffs(buf))
                {
                    status = CODEC_ERROR;
                    goto done;
                }
            }

            /* get codec */
            codec = get_wave_codec(format.formattag);
            if (!codec)
            {
                DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", 
                    (unsigned int) format.formattag);
                status = CODEC_ERROR;
                goto done;
            }

            /* riff 8bit linear pcm is unsigned */
            if (format.formattag == WAVE_FORMAT_PCM && format.bitspersample == 8)
                format.is_signed = false;

            /* check format, and calculate chunk size */
            if (!codec->set_format(&format))
            {
                status = CODEC_ERROR;
                goto done;
            }
        } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) {
            format.numbytes = size;
            /* advance to start of data */
            ci->advance_buffer(24);
            firstblockposn += 24;
            break;
        } else if (memcmp(buf, WAVE64_GUID_FACT, 16) == 0) {
            /* skip 'fact' chunk */
        } else {
            DEBUGF("unknown Wave64 chunk: "
                   "'%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'\n",
                   buf[0], buf[1], buf[ 2], buf[ 3], buf[ 4], buf[ 5], buf[ 6], buf[ 7],
                   buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
        }

        /* go to next chunk (8byte bound) */
        size += 24 + ((1 + ~size) & 0x07);

        ci->advance_buffer(size);
        firstblockposn += size;
    }

    if (!codec)
    {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n");
        status = CODEC_ERROR;
        goto done;
    }

    /* common format check */
    if (format.channels == 0) {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
        status = CODEC_ERROR;
        goto done;
    }
    if (format.samplesperblock == 0) {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n");
        status = CODEC_ERROR;
        goto done;
    }
    if (format.blockalign == 0)
    {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n");
        status = CODEC_ERROR;
        goto done;
    }
    if (format.numbytes == 0) {
        DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
        status = CODEC_ERROR;
        goto done;
    }

    /* check chunksize */
    if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels
           > PCM_SAMPLE_SIZE)
        format.chunksize = (PCM_SAMPLE_SIZE / format.blockalign) * format.blockalign;
    if (format.chunksize == 0)
    {
        DEBUGF("CODEC_ERROR: chunksize is 0\n");
        status = CODEC_ERROR;
        goto done;
    }

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    if (format.channels == 2) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
    } else if (format.channels == 1) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    } else {
        DEBUGF("CODEC_ERROR: more than 2 channels\n");
        status = CODEC_ERROR;
        goto done;
    }

    /* make sure we're at the correct offset */
    if (bytesdone > (uint32_t) firstblockposn) {
        /* Round down to previous block */
        struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
                                                     PCM_SEEK_POS, &read_buffer);

        if (newpos->pos > format.numbytes)
            goto done;
        if (ci->seek_buffer(firstblockposn + newpos->pos))
        {
            bytesdone      = newpos->pos;
            decodedsamples = newpos->samples;
        }
        ci->seek_complete();
    } else {
        /* already where we need to be */
        bytesdone = 0;
    }

    /* The main decoder loop */
    endofstream = 0;

    while (!endofstream) {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            break;
        }

        if (ci->seek_time) {
            struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME,
                                                         &read_buffer);

            if (newpos->pos > format.numbytes)
                break;
            if (ci->seek_buffer(firstblockposn + newpos->pos))
            {
                bytesdone      = newpos->pos;
                decodedsamples = newpos->samples;
            }
            ci->seek_complete();
        }

        wavbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
        if (n == 0)
            break; /* End of stream */
        if (bytesdone + n > format.numbytes) {
            n = format.numbytes - bytesdone;
            endofstream = 1;
        }

        status = codec->decode(wavbuf, n, samples, &bufcount);
        if (status == CODEC_ERROR)
        {
            DEBUGF("codec error\n");
            goto done;
        }

        ci->pcmbuf_insert(samples, NULL, bufcount);
        ci->advance_buffer(n);
        bytesdone += n;
        decodedsamples += bufcount;

        if (bytesdone >= format.numbytes)
            endofstream = 1;
        ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
    }
    status = CODEC_OK;

done:
    if (ci->request_next_track())
        goto next_track;

exit:
    return status;
}
コード例 #14
0
ファイル: wma.c プロジェクト: CrashSerious/rockbox_psgroove
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;
    size_t resume_offset;
    int i;
    int wmares, res;
    uint8_t* audiobuf;
    int audiobufsize;
    int packetlength = 0;
    int errcount = 0;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 29);

next_track:

    /* Wait for the metadata to be read */
    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    retval = CODEC_OK;

    /* Remember the resume position - when the codec is opened, the
       playback engine will reset it. */
    resume_offset = ci->id3->offset;
restart_track:
    if (codec_init()) {
        LOGF("WMA: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    if (wma_decode_init(&wmadec,&wfx) < 0) {
        LOGF("WMA: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    if (resume_offset > ci->id3->first_frame_offset)
    {
        /* Get start of current packet */
        int packet_offset = (resume_offset - ci->id3->first_frame_offset)
            % wfx.packet_size;
        ci->seek_buffer(resume_offset - packet_offset);
        elapsedtime = asf_get_timestamp(&i);
        ci->set_elapsed(elapsedtime);
    }
    else
    {
        /* Now advance the file position to the first frame */
        ci->seek_buffer(ci->id3->first_frame_offset);
        elapsedtime = 0;
    }

    resume_offset = 0;
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    /* The main decoding loop */

    res = 1;
    while (res >= 0)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }

        /* Deal with any pending seek requests */
        if (ci->seek_time){

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1){
                ci->seek_complete();
                goto next_track;
            }
            /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/
            ci->set_elapsed(elapsedtime);

            /*flush the wma decoder state*/
            wmadec.last_superframe_len = 0;
            wmadec.last_bitoffset = 0;
            ci->seek_complete();
        }
        errcount = 0;
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            /* We'll try to recover from a parse error a certain number of
             * times. If we succeed, the error counter will be reset.
             */

            errcount++;
            DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
            if (errcount > 5) {
                goto done;
            } else {
                ci->advance_buffer(packetlength);
                goto new_packet;
            }
        } else if (res > 0) {
            wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);

            for (i=0; i < wmadec.nb_frames; i++)
            {
                wmares = wma_decode_superframe_frame(&wmadec,
                                                     audiobuf, audiobufsize);

                ci->yield ();

                if (wmares < 0) {
                    /* Do the above, but for errors in decode. */
                    errcount++;
                    DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
                    if (errcount > 5) {
                        goto done;
                    } else {
                        ci->advance_buffer(packetlength);
                        goto new_packet;
                    }
                } else if (wmares > 0) {
                    ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
                    elapsedtime += (wmares*10)/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                }
                ci->yield();
            }
        }

        ci->advance_buffer(packetlength);
    }
    retval = CODEC_OK;

done:
    /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/

    if (ci->request_next_track())
        goto next_track;
exit:
    return retval;
}
コード例 #15
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    /* Note that when dealing with QuickTime/MPEG4 files, terminology is
     * a bit confusing. Files with sound are split up in chunks, where
     * each chunk contains one or more samples. Each sample in turn
     * contains a number of "sound samples" (the kind you refer to with
     * the sampling frequency).
     */
    size_t n;
    demux_res_t demux_res;
    stream_t input_stream;
    uint32_t sound_samples_done;
    uint32_t elapsed_time;
    int file_offset;
    int framelength;
    int lead_trim = 0;
    unsigned int frame_samples;
    unsigned int i;
    unsigned char* buffer;
    NeAACDecFrameInfo frame_info;
    NeAACDecHandle decoder;
    int err;
    uint32_t seek_idx = 0;
    uint32_t s = 0;
    uint32_t sbr_fac = 1;
    unsigned char c = 0;
    void *ret;
    intptr_t param;
    bool empty_first_frame = false;

    /* Clean and initialize decoder structures */
    memset(&demux_res , 0, sizeof(demux_res));
    if (codec_init()) {
        LOGF("FAAD: Codec init error\n");
        return CODEC_ERROR;
    }

    file_offset = ci->id3->offset;

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    stream_create(&input_stream,ci);

    ci->seek_buffer(ci->id3->first_frame_offset);

    /* if qtmovie_read returns successfully, the stream is up to
     * the movie data, which can be used directly by the decoder */
    if (!qtmovie_read(&input_stream, &demux_res)) {
        LOGF("FAAD: File init error\n");
        return CODEC_ERROR;
    }

    /* initialise the sound converter */
    decoder = NeAACDecOpen();

    if (!decoder) {
        LOGF("FAAD: Decode open error\n");
        return CODEC_ERROR;
    }

    NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
    conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
    NeAACDecSetConfiguration(decoder, conf);

    err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
    if (err) {
        LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
        return CODEC_ERROR;
    }

#ifdef SBR_DEC
    /* Check for need of special handling for seek/resume and elapsed time. */
    if (ci->id3->needs_upsampling_correction) {
        sbr_fac = 2;
    } else {
        sbr_fac = 1;
    }
#endif

    i = 0;
    
    if (file_offset > 0) {
        /* Resume the desired (byte) position. Important: When resuming SBR
         * upsampling files the resulting sound_samples_done must be expanded 
         * by a factor of 2. This is done via using sbr_fac. */
        if (m4a_seek_raw(&demux_res, &input_stream, file_offset,
                          &sound_samples_done, (int*) &i)) {
            sound_samples_done *= sbr_fac;
        } else {
            sound_samples_done = 0;
        }
        NeAACDecPostSeekReset(decoder, i);
    } else {
        sound_samples_done = 0;
    }

    elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
    ci->set_elapsed(elapsed_time);
    
    if (i == 0) 
    {
        lead_trim = ci->id3->lead_trim;
    }

    /* The main decoding loop */
    while (i < demux_res.num_sample_byte_sizes) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {
            /* Seek to the desired time position. Important: When seeking in SBR
             * upsampling files the seek_time must be divided by 2 when calling 
             * m4a_seek and the resulting sound_samples_done must be expanded 
             * by a factor 2. This is done via using sbr_fac. */
            if (m4a_seek(&demux_res, &input_stream,
                          (param/10/sbr_fac)*(ci->id3->frequency/100),
                          &sound_samples_done, (int*) &i)) {
                sound_samples_done *= sbr_fac;
                elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
                ci->set_elapsed(elapsed_time);
                seek_idx = 0;

                if (i == 0) 
                {
                    lead_trim = ci->id3->lead_trim;
                }
            }
            NeAACDecPostSeekReset(decoder, i);
            ci->seek_complete();
        }

        /* There can be gaps between chunks, so skip ahead if needed. It
         * doesn't seem to happen much, but it probably means that a 
         * "proper" file can have chunks out of order. Why one would want
         * that an good question (but files with gaps do exist, so who 
         * knows?), so we don't support that - for now, at least.
         */
        file_offset = m4a_check_sample_offset(&demux_res, i, &seek_idx);

        if (file_offset > ci->curpos)
        {
            ci->advance_buffer(file_offset - ci->curpos);
        }
        else if (file_offset == 0)
        {
            LOGF("AAC: get_sample_offset error\n");
            return CODEC_ERROR;
        }
        
        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);

        /* Decode one block - returned samples will be host-endian */
        ret = NeAACDecDecode(decoder, &frame_info, buffer, n);

        /* NeAACDecDecode may sometimes return NULL without setting error. */
        if (ret == NULL || frame_info.error > 0) {
            LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
            return CODEC_ERROR;
        }

        /* Advance codec buffer (no need to call set_offset because of this) */
        ci->advance_buffer(frame_info.bytesconsumed);

        /* Output the audio */
        ci->yield();
        
        frame_samples = frame_info.samples >> 1;

        if (empty_first_frame)
        {
            /* Remove the first frame from lead_trim, under the assumption
             * that it had the same size as this frame
             */
            empty_first_frame = false;
            lead_trim -= frame_samples;

            if (lead_trim < 0)
            {
                lead_trim = 0;
            }
        }

        /* Gather number of samples for the decoded frame. */
        framelength = frame_samples - lead_trim;
        
        if (i == demux_res.num_sample_byte_sizes - 1)
        {
            // Size of the last frame
            const uint32_t sample_duration = (demux_res.num_time_to_samples > 0) ?
                demux_res.time_to_sample[demux_res.num_time_to_samples - 1].sample_duration :
                frame_samples;

            /* Currently limited to at most one frame of tail_trim.
             * Seems to be enough.
             */
            if (ci->id3->tail_trim == 0 && sample_duration < frame_samples)
            {
                /* Subtract lead_trim just in case we decode a file with only
                 * one audio frame with actual data (lead_trim is usually zero
                 * here).
                 */
                framelength = sample_duration - lead_trim;
            }
            else
            {
                framelength -= ci->id3->tail_trim;
            }
        }

        if (framelength > 0)
        {
            ci->pcmbuf_insert(&decoder->time_out[0][lead_trim],
                              &decoder->time_out[1][lead_trim],
                              framelength);
            sound_samples_done += framelength;
            /* Update the elapsed-time indicator */
            elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
            ci->set_elapsed(elapsed_time);
        }

        if (lead_trim > 0)
        {
            /* frame_info.samples can be 0 for frame 0. We still want to
             * remove it from lead_trim, so do that during frame 1.
             */
            if (0 == i && 0 == frame_info.samples)
            {
                empty_first_frame = true;
            }

            lead_trim -= frame_samples;

            if (lead_trim < 0)
            {
                lead_trim = 0;
            }
        }

        ++i;
    }

    LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done);
    return CODEC_OK;
}
コード例 #16
0
ファイル: opus.c プロジェクト: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;
    intptr_t param;
    ogg_sync_state oy;
    ogg_page og;
    ogg_packet op;
    ogg_stream_state os;
    int64_t page_granule = 0;
    int stream_init = 0;
    int sample_rate = 48000;
    OpusDecoder *st = NULL;
    OpusHeader header;
    int ret;
    unsigned long strtoffset = ci->id3->offset;
    int skip = 0;
    int64_t seek_target;
    uint64_t granule_pos;

    ogg_malloc_init();

    global_stack = 0;

#if defined(CPU_COLDFIRE)
    /* EMAC rounding is disabled because of MULT16_32_Q15, which will be
       inaccurate with rounding in its current incarnation */
    coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
#endif

    /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */
    ogg_sync_init(&oy);
    oy.storage = 64*1024;
    oy.data = _ogg_malloc(oy.storage);

    /* allocate output buffer */
    uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t));

    ci->seek_buffer(0);
    ci->set_elapsed(0);

    while (1) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            if (st != NULL) {
                /* calculate granule to seek to (including seek rewind) */
                seek_target = (48LL * param) + header.preskip;
                skip = MIN(seek_target, SEEK_REWIND);
                seek_target -= skip;

                LOGF("Opus seek page:%lld,%lld,%ld\n",
		            seek_target, page_granule, (long)param);
                speex_seek_page_granule(seek_target, page_granule, &oy, &os);
            }

            ci->set_elapsed(param);
            ci->seek_complete();
        }

        /*Get the ogg buffer for writing*/
        if (get_more_data(&oy) < 1) {
            goto done;
        }

        /* Loop for all complete pages we got (most likely only one) */
        while (ogg_sync_pageout(&oy, &og) == 1) {
            if (stream_init == 0) {
                ogg_stream_init(&os, ogg_page_serialno(&og));
                stream_init = 1;
            }

            /* Add page to the bitstream */
            ogg_stream_pagein(&os, &og);

            page_granule = ogg_page_granulepos(&og);
            granule_pos = page_granule;

            /* Do this to avoid allocating space for huge comment packets
               (embedded Album Art) */
            if(os.packetno == 1 && ogg_stream_packetpeek(&os, &op) != 1){
              ogg_sync_reset(&oy);
            }

            while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) {
                if (op.packetno == 0){
                    /* identification header */
                
                    if (opus_header_parse(op.packet, op.bytes, &header) == 0) {
                        LOGF("Could not parse header");
                        goto done;
                    }
                    skip = header.preskip;

                    st = opus_decoder_create(sample_rate, header.channels, &ret);
                    if (ret != OPUS_OK) {
                        LOGF("opus_decoder_create failed %d", ret);
                        goto done;
                    }
                    LOGF("Decoder inited");

                    codec_set_replaygain(ci->id3);

                    opus_decoder_ctl(st, OPUS_SET_GAIN(header.gain));

                    ci->configure(DSP_SET_FREQUENCY, sample_rate);
                    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
                    ci->configure(DSP_SET_STEREO_MODE, (header.channels == 2) ?
                        STEREO_INTERLEAVED : STEREO_MONO);

                } else if (op.packetno == 1) {
                    /* Comment header */
                } else {
                    if (strtoffset) {
                        ci->seek_buffer(strtoffset);
                        ogg_sync_reset(&oy);
                        strtoffset = 0;
                        break;//next page
                    }

                    /* report progress */
                    ci->set_elapsed((granule_pos - header.preskip) / 48);

                    /* Decode audio packets */
                    ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0);

                    if (ret > 0) {
                        if (skip > 0) {
                            if (ret <= skip) {
                                /* entire output buffer is skipped */
                                skip -= ret;
                                ret = 0;
                            } else {
                                /* part of output buffer is played */
                                ret -= skip;
                                ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
                                skip = 0;
                            }
                        } else {
                            /* entire buffer is played */
                            ci->pcmbuf_insert(output, NULL, ret);
                        }
                        granule_pos += ret;
                    } else {
                        if (ret < 0) {
                            LOGF("opus_decode failed %d", ret);
                            goto done;
                        }
                        break;
                    }
                }
            }
        }
    }
    LOGF("Returned OK");
    error = CODEC_OK;
done:
    ogg_malloc_destroy();
    return error;
}
コード例 #17
0
ファイル: mpc.c プロジェクト: eisnerd/rockbox
/* This is the codec entry point. */
enum codec_status codec_main(void)
{
    mpc_int64_t samplesdone;
    uint32_t frequency;     /* 0.1 kHz accuracy */
    uint32_t elapsed_time;  /* milliseconds */
    uint32_t byterate;      /* bytes per second */
    mpc_status status;
    mpc_reader reader;
    mpc_streaminfo info;
    mpc_frame_info frame;
    mpc_demux *demux = NULL;
    int retval = CODEC_OK;
    
    frame.buffer = sample_buffer;
    
    /* musepack's sample representation is 18.14
     * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
    
    /* Create a decoder instance */
    reader.read     = read_impl;
    reader.seek     = seek_impl;
    reader.tell     = tell_impl;
    reader.get_size = get_size_impl;

next_track:    
    if (codec_init()) 
    {
        retval = CODEC_ERROR;
        goto exit;
    }

    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    /* Initialize demux/decoder. */
    demux = mpc_demux_init(&reader);
    if (NULL == demux)
    {
        retval = CODEC_ERROR;
        goto done;
    }
    /* Read file's streaminfo data. */
    mpc_demux_get_info(demux, &info);
    
    byterate  = (mpc_uint32_t)(info.average_bitrate) / 8;
    frequency = info.sample_freq / 100; /* 0.1 kHz accuracy */
    ci->configure(DSP_SWITCH_FREQUENCY, info.sample_freq);

    /* Remark: rockbox offset is the file offset in bytes. So, estimate the 
     * sample seek position from the file offset, the sampling frequency and
     * the bitrate. As the saved position is exactly calculated the reverse way 
     * there is no loss of information except rounding. */
    samplesdone = 100 * ((mpc_uint64_t)(ci->id3->offset * frequency) / byterate);
        
    /* Set up digital signal processing for correct number of channels */
    /* NOTE: current musepack format only allows for stereo files
       but code is here to handle other configurations anyway */
    if      (info.channels == 2)
        ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    else if (info.channels == 1)
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    else 
    {
       retval = CODEC_ERROR;
       goto done;
    }
    
    codec_set_replaygain(ci->id3);

    /* Resume to saved sample offset. */
    if (samplesdone > 0) 
    {
        if (mpc_demux_seek_sample(demux, samplesdone) == MPC_STATUS_OK) 
        {
            elapsed_time = (samplesdone*10)/frequency;
            ci->set_elapsed(elapsed_time);
        } 
        else 
        {
            samplesdone = 0;
        }
    }

    /* This is the decoding loop. */
    do 
    {
        /* Complete seek handler. */
        if (ci->seek_time) 
        {
            mpc_int64_t new_offset = ((ci->seek_time - 1)/10)*frequency;
            if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) 
            {
                samplesdone = new_offset;
                ci->set_elapsed(ci->seek_time);
            }
            ci->seek_complete();
        }
        
        /* Stop or skip occured, exit decoding loop. */
        if (ci->stop_codec || ci->new_track)
            break;

        /* Decode one frame. */
        status = mpc_demux_decode(demux, &frame);
        ci->yield();
        if (frame.bits == -1)
        {
            /* Decoding error, exit decoding loop. */
            retval = (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR;
            goto done;
        } 
        else 
        {
            /* Decoding passed, insert samples to PCM buffer. */
            ci->pcmbuf_insert(frame.buffer,
                              frame.buffer + MPC_FRAME_LENGTH,
                              frame.samples);
            samplesdone += frame.samples;
            elapsed_time = (samplesdone*10)/frequency;
            ci->set_elapsed(elapsed_time);
            /* Remark: rockbox offset is the file offset in bytes. So estimate 
             * this offset from the samples, sampling frequency and bitrate */
            ci->set_offset( (samplesdone * byterate)/(frequency*100) );
        }
    } while (true);

done:
    if (ci->request_next_track())
        goto next_track;

exit:
    return retval;
}
コード例 #18
0
ファイル: aac_bsf.c プロジェクト: Rockbox/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    size_t n;
    int32_t bread;
    unsigned int frame_samples;
    uint32_t s = 0;
    unsigned char c = 0;
    long action = CODEC_ACTION_NULL;
    intptr_t param;
    unsigned char* buffer;
    NeAACDecFrameInfo frame_info;
    NeAACDecHandle decoder;
    NeAACDecConfigurationPtr conf;

    /* Clean and initialize decoder structures */
    if (codec_init()) {
        LOGF("FAAD: Codec init error\n");
        return CODEC_ERROR;
    }

    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    ci->seek_buffer(ci->id3->first_frame_offset);

    /* initialise the sound converter */
    decoder = NeAACDecOpen();

    if (!decoder) {
        LOGF("FAAD: Decode open error\n");
        return CODEC_ERROR;
    }

    conf = NeAACDecGetCurrentConfiguration(decoder);
    conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
    NeAACDecSetConfiguration(decoder, conf);

    buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
    bread = NeAACDecInit(decoder, buffer, n, &s, &c);
    if (bread < 0) {
        LOGF("FAAD: DecInit: %ld, %d\n", bread, decoder->object_type);
        return CODEC_ERROR;
    }
    ci->advance_buffer(bread);

    if (ci->id3->offset > ci->id3->first_frame_offset) {
        /* Resume the desired (byte) position. */
        ci->seek_buffer(ci->id3->offset);
        NeAACDecPostSeekReset(decoder, 0);
        update_playing_time();
    } else if (ci->id3->elapsed) {
        action = CODEC_ACTION_SEEK_TIME;
        param = ci->id3->elapsed;
    } else {
        ci->set_elapsed(0);
        ci->set_offset(ci->id3->first_frame_offset);
    }

    /* The main decoding loop */
    while (1) {
        if (action == CODEC_ACTION_NULL)
            action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {
            /* Seek to the desired time position. */
            ci->seek_buffer(ci->id3->first_frame_offset + (uint32_t)((uint64_t)param * ci->id3->bitrate / 8));
            ci->set_elapsed((unsigned long)param);
            NeAACDecPostSeekReset(decoder, 0);
            ci->seek_complete();
        }

        action = CODEC_ACTION_NULL;

        /* Request the required number of bytes from the input buffer */
        buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);

        if (n == 0) /* End of Stream */
            break;

        /* Decode one block - returned samples will be host-endian */
        if (NeAACDecDecode(decoder, &frame_info, buffer, n) == NULL || frame_info.error > 0) {
            LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
            return CODEC_ERROR;
        }

        /* Advance codec buffer (no need to call set_offset because of this) */
        ci->advance_buffer(frame_info.bytesconsumed);

        /* Output the audio */
        ci->yield();
        frame_samples = frame_info.samples >> 1;
        ci->pcmbuf_insert(&decoder->time_out[0][0], &decoder->time_out[1][0], frame_samples);

        /* Update the elapsed-time indicator */
        update_playing_time();
    }

    LOGF("AAC: Decoding complete\n");
    return CODEC_OK;
}
コード例 #19
0
ファイル: wav.c プロジェクト: IlVerz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    uint32_t decodedsamples;
    size_t n;
    int bufcount;
    int endofstream;
    unsigned char *buf;
    uint8_t *wavbuf;
    off_t firstblockposn;     /* position of the first block in file */
    const struct pcm_codec *codec;
    uint32_t size;
    intptr_t param;

    if (codec_init()) {
        DEBUGF("codec_init() error\n");
        return CODEC_ERROR;
    }

    codec_set_replaygain(ci->id3);
    
    /* Need to save offset for later use (cleared indirectly by advance_buffer) */
    bytesdone = ci->id3->offset;

    /* get RIFF chunk header */
    ci->seek_buffer(0);
    buf = ci->request_buffer(&n, 12);
    if (n < 12) {
        DEBUGF("request_buffer error\n");
        return CODEC_ERROR;
    }
    if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) {
        DEBUGF("CODEC_ERROR: missing riff header\n");
        return CODEC_ERROR;
    }

    /* advance to first WAVE chunk */
    ci->advance_buffer(12);

    firstblockposn = 12;
    ci->memset(&format, 0, sizeof(struct pcm_format));
    format.is_signed = true;
    format.is_little_endian = true;

    decodedsamples = 0;
    codec = 0;

    /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */
    while (true) {
        /* get WAVE chunk header */
        buf = ci->request_buffer(&n, 1024);
        if (n < 8) {
            DEBUGF("data chunk request_buffer error\n");
            /* no more chunks, 'data' chunk must not have been found */
            return CODEC_ERROR;
        }

        /* chunkSize */
        size = (buf[4]|(buf[5]<<8)|(buf[6]<<16)|(buf[7]<<24));
        if (memcmp(buf, "fmt ", 4) == 0) {
            if (size < 16) {
                DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n",
                       (unsigned long)size);
                return CODEC_ERROR;
            }
            /* wFormatTag */
            format.formattag=buf[8]|(buf[9]<<8);
            /* wChannels */
            format.channels=buf[10]|(buf[11]<<8);
            /* skipping dwSamplesPerSec */
            /* skipping dwAvgBytesPerSec */
            /* wBlockAlign */
            format.blockalign=buf[20]|(buf[21]<<8);
            /* wBitsPerSample */
            format.bitspersample=buf[22]|(buf[23]<<8);
            if (format.formattag != WAVE_FORMAT_PCM) {
                if (size < 18) {
                    /* this is not a fatal error with some formats,
                     * we'll see later if we can't decode it */
                    DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) "
                           "doesn't have ext. fmt descr (chunksize=%d<18).\n",
                           (unsigned int)format.formattag, (int)size);
                }
                else
                {
                    if (format.formattag != WAVE_FORMAT_EXTENSIBLE)
                        format.samplesperblock = buf[26]|(buf[27]<<8);
                    else
                    {
                        format.size = buf[24]|(buf[25]<<8);
                        if (format.size < 22) {
                            DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
                                   "missing extension\n");
                            return CODEC_ERROR;
                        }
                        /* wValidBitsPerSample */
                        format.bitspersample = buf[26]|(buf[27]<<8);
                        /* skipping dwChannelMask (4bytes) */
                        /* SubFormat (only get the first two bytes) */
                        format.formattag = buf[32]|(buf[33]<<8);
                    }
                }
            }

            /* msadpcm specific */
            if (format.formattag == WAVE_FORMAT_ADPCM)
            {
                if (!set_msadpcm_coeffs(buf))
                {
                    return CODEC_ERROR;
                }
            }

            /* get codec */
            codec = get_wave_codec(format.formattag);
            if (!codec)
            {
                DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", 
                    (unsigned int) format.formattag);
                return CODEC_ERROR;
            }

            /* riff 8bit linear pcm is unsigned */
            if (format.formattag == WAVE_FORMAT_PCM && format.bitspersample == 8)
                format.is_signed = false;

            /* set format, parse codec specific tag, check format, and calculate chunk size */
            if (!codec->set_format(&format))
            {
                return CODEC_ERROR;
            }
        } else if (memcmp(buf, "data", 4) == 0) {
            format.numbytes = size;
            /* advance to start of data */
            ci->advance_buffer(8);
            firstblockposn += 8;
            break;
        } else if (memcmp(buf, "fact", 4) == 0) {
            /* dwSampleLength */
            if (size >= 4)
                format.totalsamples =
                             (buf[8]|(buf[9]<<8)|(buf[10]<<16)|(buf[11]<<24));
        } else {
            DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n",
                   buf[0], buf[1], buf[2], buf[3], (unsigned long)size);
        }

        /* go to next chunk (even chunk sizes must be padded) */
        size += 8 + (size & 0x01);

        ci->advance_buffer(size);
        firstblockposn += size;
    }

    if (!codec)
    {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n");
        return CODEC_ERROR;
    }

    /* common format check */
    if (format.channels == 0) {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
        return CODEC_ERROR;
    }
    if (format.samplesperblock == 0) {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n");
        return CODEC_ERROR;
    }
    if (format.blockalign == 0)
    {
        DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n");
        return CODEC_ERROR;
    }
    if (format.numbytes == 0) {
        DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
        return CODEC_ERROR;
    }

    /* check chunksize */
    if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels
           > PCM_SAMPLE_SIZE)
        format.chunksize = (PCM_SAMPLE_SIZE / format.blockalign) * format.blockalign;
    if (format.chunksize == 0)
    {
        DEBUGF("CODEC_ERROR: chunksize is 0\n");
        return CODEC_ERROR;
    }

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    if (format.channels == 2) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
    } else if (format.channels == 1) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    } else {
        DEBUGF("CODEC_ERROR: more than 2 channels\n");
        return CODEC_ERROR;
    }

    /* make sure we're at the correct offset */
    if (bytesdone > (uint32_t) firstblockposn) {
        /* Round down to previous block */
        struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
                                                     PCM_SEEK_POS, &read_buffer);

        if (newpos->pos > format.numbytes)
            return CODEC_OK;
        if (ci->seek_buffer(firstblockposn + newpos->pos))
        {
            bytesdone      = newpos->pos;
            decodedsamples = newpos->samples;
        }
    } else {
        /* already where we need to be */
        bytesdone = 0;
    }

    /* The main decoder loop */
    endofstream = 0;

    while (!endofstream) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
                                                         &read_buffer);
            if (newpos->pos > format.numbytes)
            {
                ci->set_elapsed(ci->id3->length);
                ci->seek_complete();
                break;
            }

            if (ci->seek_buffer(firstblockposn + newpos->pos))
            {
                bytesdone      = newpos->pos;
                decodedsamples = newpos->samples;
            }

            ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
            ci->seek_complete();
        }

        wavbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
        if (n == 0)
            break; /* End of stream */
        if (bytesdone + n > format.numbytes) {
            n = format.numbytes - bytesdone;
            endofstream = 1;
        }

        if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR)
        {
            DEBUGF("codec error\n");
            return CODEC_ERROR;
        }

        ci->pcmbuf_insert(samples, NULL, bufcount);
        ci->advance_buffer(n);
        bytesdone += n;
        decodedsamples += bufcount;

        if (bytesdone >= format.numbytes)
            endofstream = 1;
        ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
    }

    return CODEC_OK;
}
コード例 #20
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    tta_info info;
    int status;
    unsigned int decodedsamples;
    int endofstream;
    int new_pos = 0;
    int sample_count;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
  
next_track:
    status = CODEC_OK;

    if (codec_init())
    {
        DEBUGF("codec_init() error\n");
        status = CODEC_ERROR;
        goto exit;
    }

    if (codec_wait_taginfo() != 0)
        goto done;

    if (set_tta_info(&info) < 0 || player_init(&info) < 0)
    {
        status = CODEC_ERROR;
        goto exit;
    }

    codec_set_replaygain(ci->id3);

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    if (info.NCH == 2) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
    } else if (info.NCH == 1) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    } else {
        DEBUGF("CODEC_ERROR: more than 2 channels\n");
        status = CODEC_ERROR;
        goto done;
    }

    /* The main decoder loop */
    decodedsamples = 0;
    endofstream = 0;

    if (ci->id3->offset > 0)
    {
        /* Need to save offset for later use (cleared indirectly by advance_buffer) */
        new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
        if (new_pos >= 0)
            decodedsamples = new_pos;
        ci->seek_complete();
    }

    while (!endofstream)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track)
            break;

        if (ci->seek_time)
        {
            new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME);
            if (new_pos >= 0)
            {
                decodedsamples = new_pos;
                ci->seek_complete();
            }
        }

        sample_count = get_samples(samples);
        if (sample_count < 0)
        {
            status = CODEC_ERROR;
            break;
        }
        ci->pcmbuf_insert(samples, NULL, sample_count);
        decodedsamples += sample_count;
        if (decodedsamples >= info.DATALENGTH)
            endofstream = 1;
        ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
    }

done:
    player_stop();
    if (ci->request_next_track())
        goto next_track;

exit:
    return status;
}
コード例 #21
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    uint32_t elapsedtime;
    asf_waveformatex_t wfx;
    size_t resume_offset;
    int i;
    int wmares;
    int res = 0;
    uint8_t* audiobuf;
    int audiobufsize;
    int packetlength = 0;
    int errcount = 0;
    intptr_t param;

    /* Proper reset of the decoder context. */
    memset(&wmadec, 0, sizeof(wmadec));

    /* Remember the resume position - when the codec is opened, the
       playback engine will reset it. */
    resume_offset = ci->id3->offset;

restart_track:
    if (codec_init()) {
        LOGF("WMA: Error initialising codec\n");
        return CODEC_ERROR;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));

    ci->seek_buffer(ci->id3->first_frame_offset);
    if (wma_decode_init(&wmadec,&wfx) < 0) {
        LOGF("WMA: Unsupported or corrupt file\n");
        return CODEC_ERROR;
    }

    if (resume_offset > ci->id3->first_frame_offset)
    {
        /* Get start of current packet */
        int packet_offset = (resume_offset - ci->id3->first_frame_offset)
            % wfx.packet_size;
        ci->seek_buffer(resume_offset - packet_offset);
        elapsedtime = asf_get_timestamp(&i);
    }
    else
    {
        /* Now advance the file position to the first frame */
        ci->seek_buffer(ci->id3->first_frame_offset);
        elapsedtime = 0;
    }

    ci->set_elapsed(elapsedtime);

    resume_offset = 0;
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    /* The main decoding loop */
    while (res >= 0)
    {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /* Deal with any pending seek requests */
        if (action == CODEC_ACTION_SEEK_TIME) {

            if (param == 0) {
                ci->set_elapsed(0);
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(param, &wfx);
            if (elapsedtime < 1){
                ci->set_elapsed(0);
                ci->seek_complete();
                break;
            }
            /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/

            /*flush the wma decoder state*/
            wmadec.last_superframe_len = 0;
            wmadec.last_bitoffset = 0;

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }
        errcount = 0;
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            /* We'll try to recover from a parse error a certain number of
             * times. If we succeed, the error counter will be reset.
             */

            if (res == ASF_ERROR_EOF) {
                /* File ended - not an error */
                break;
            }

            errcount++;
            DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
            if (errcount > 5) {
                return CODEC_ERROR;
            } else {
                ci->advance_buffer(packetlength);
                goto new_packet;
            }
        } else if (res > 0) {
            wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);

            for (i=0; i < wmadec.nb_frames; i++)
            {
                wmares = wma_decode_superframe_frame(&wmadec,
                                                     audiobuf, audiobufsize);

                ci->yield ();

                if (wmares < 0) {
                    /* Do the above, but for errors in decode. */
                    errcount++;
                    DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
                    if (errcount > 5) {
                        return CODEC_ERROR;
                    } else {
                        ci->advance_buffer(packetlength);
                        goto new_packet;
                    }
                } else if (wmares > 0) {
                    ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
                    elapsedtime += (wmares*10)/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                }
            }
        }

        ci->advance_buffer(packetlength);
    }

    /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/
    return CODEC_OK;
}
コード例 #22
0
ファイル: au.c プロジェクト: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    struct pcm_format format;
    uint32_t bytesdone, decodedsamples;
    size_t n;
    int bufcount;
    int endofstream;
    unsigned char *buf;
    uint8_t *aubuf;
    off_t firstblockposn;     /* position of the first block in file */
    const struct pcm_codec *codec;
    int offset = 0;
    intptr_t param;
 
    if (codec_init()) {
        DEBUGF("codec_init() error\n");
        return CODEC_ERROR;
    }

    codec_set_replaygain(ci->id3);
    
    /* Need to save offset for later use (cleared indirectly by advance_buffer) */
    bytesdone = ci->id3->offset;

    ci->memset(&format, 0, sizeof(struct pcm_format));
    format.is_signed = true;
    format.is_little_endian = false;

    /* set format */
    ci->seek_buffer(0);
    buf = ci->request_buffer(&n, 24);
    if (n < 24 || (memcmp(buf, ".snd", 4) != 0))
    {
        /*
         * headerless sun audio file
         * It is decoded under conditions.
         *     format:    G.711 mu-law
         *     channel:   mono
         *     frequency: 8000 kHz
         */
        offset = 0;
        format.formattag     = AU_FORMAT_MULAW;
        format.channels      = 1;
        format.bitspersample = 8;
        format.numbytes      = ci->id3->filesize;
    }
    else
    {
        /* parse header */

        /* data offset */
        offset = get_be32(buf + 4);
        if (offset < 24)
        {
            DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset);
            return CODEC_ERROR;
        }
        /* data size */
        format.numbytes = get_be32(buf + 8);
        if (format.numbytes == (uint32_t)0xffffffff)
            format.numbytes = ci->id3->filesize - offset;
        /* encoding */
        format.formattag = convert_au_format(get_be32(buf + 12), &format);
        if (format.formattag == AU_FORMAT_UNSUPPORT)
        {
            DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12));
            return CODEC_ERROR;
        }
        /* skip sample rate */
        format.channels = get_be32(buf + 20);
    }

    /* advance to first WAVE chunk */
    ci->advance_buffer(offset);

    firstblockposn = offset;

    decodedsamples = 0;
    codec = 0;

    /* get codec */
    codec = get_au_codec(format.formattag);
    if (!codec)
    {
        DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag);
        return CODEC_ERROR;
    }

    if (!codec->set_format(&format))
    {
        return CODEC_ERROR;
    }

    if (format.numbytes == 0) {
        DEBUGF("CODEC_ERROR: data size is 0\n");
        return CODEC_ERROR;
    }

    /* check chunksize */
    if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels
           > PCM_SAMPLE_SIZE)
        format.chunksize = (PCM_SAMPLE_SIZE / format.blockalign) * format.blockalign;
    if (format.chunksize == 0)
    {
        DEBUGF("CODEC_ERROR: chunksize is 0\n");
        return CODEC_ERROR;
    }

    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
    if (format.channels == 2) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
    } else if (format.channels == 1) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    } else {
        DEBUGF("CODEC_ERROR: more than 2 channels\n");
        return CODEC_ERROR;
    }

    /* make sure we're at the correct offset */
    if (bytesdone > (uint32_t) firstblockposn) {
        /* Round down to previous block */
        struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
                                                     PCM_SEEK_POS, NULL);

        if (newpos->pos > format.numbytes)
            goto done;
        if (ci->seek_buffer(firstblockposn + newpos->pos))
        {
            bytesdone      = newpos->pos;
            decodedsamples = newpos->samples;
        }
    } else {
        /* already where we need to be */
        bytesdone = 0;
    }

    ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);

    /* The main decoder loop */
    endofstream = 0;

    while (!endofstream) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports.  */
            struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);

            if (newpos->pos > format.numbytes)
            {
                ci->set_elapsed(ci->id3->length);
                ci->seek_complete();
                break;
            }

            if (ci->seek_buffer(firstblockposn + newpos->pos))
            {
                bytesdone      = newpos->pos;
                decodedsamples = newpos->samples;
            }

            ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
            ci->seek_complete();
        }

        aubuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
        if (n == 0)
            break; /* End of stream */
        if (bytesdone + n > format.numbytes) {
            n = format.numbytes - bytesdone;
            endofstream = 1;
        }

        if (codec->decode(aubuf, n, samples, &bufcount) == CODEC_ERROR)
        {
            DEBUGF("codec error\n");
            return CODEC_ERROR;
        }

        ci->pcmbuf_insert(samples, NULL, bufcount);
        ci->advance_buffer(n);
        bytesdone += n;
        decodedsamples += bufcount;

        if (bytesdone >= format.numbytes)
            endofstream = 1;
        ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
    }

done:
    return CODEC_OK;
}
コード例 #23
0
ファイル: ape.c プロジェクト: claymodel/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    struct ape_ctx_t ape_ctx;
    uint32_t samplesdone;
    uint32_t elapsedtime;
    size_t bytesleft;
    int retval;

    uint32_t currentframe;
    uint32_t newfilepos;
    uint32_t samplestoskip;
    int nblocks;
    int bytesconsumed;
    unsigned char* inbuffer;
    uint32_t blockstodecode;
    int res;
    int firstbyte;
    size_t resume_offset;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);

next_track:
    retval = CODEC_OK;

    if (codec_init()) {
        LOGF("APE: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    if (codec_wait_taginfo() != 0)
        goto done;

    /* Remember the resume position - when the codec is opened, the
       playback engine will reset it. */
    resume_offset = ci->id3->offset;

    inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);

    /* Read the file headers to populate the ape_ctx struct */
    if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) {
        LOGF("APE: Error reading header\n");
        retval = CODEC_ERROR;
        goto exit;
    }

    /* Initialise the seektable for this file */
    ape_ctx.seektable = seektablebuf;
    ape_ctx.numseekpoints = MIN(MAX_SEEKPOINTS,ape_ctx.numseekpoints);

    ci->advance_buffer(ape_ctx.seektablefilepos);

    /* The seektable may be bigger than the guard buffer (32KB), so we
       do a read() */
    ci->read_filebuf(ape_ctx.seektable, ape_ctx.numseekpoints * sizeof(uint32_t));

#ifdef ROCKBOX_BIG_ENDIAN
    /* Byte-swap the little-endian seekpoints */
    {
        uint32_t i;

        for(i = 0; i < ape_ctx.numseekpoints; i++)
            ape_ctx.seektable[i] = swap32(ape_ctx.seektable[i]);
    }
#endif

    /* Now advance the file position to the first frame */
    ci->advance_buffer(ape_ctx.firstframe - 
                       (ape_ctx.seektablefilepos +
                        ape_ctx.numseekpoints * sizeof(uint32_t)));

    ci->configure(DSP_SWITCH_FREQUENCY, ape_ctx.samplerate);
    ci->configure(DSP_SET_STEREO_MODE, ape_ctx.channels == 1 ?
                  STEREO_MONO : STEREO_NONINTERLEAVED);
    codec_set_replaygain(ci->id3);

    /* The main decoding loop */

    if (resume_offset) {
        /* The resume offset is a value in bytes - we need to
           turn it into a frame number and samplestoskip value */

        ape_resume(&ape_ctx, resume_offset, 
                   &currentframe, &samplesdone, &samplestoskip, &firstbyte);
    } else {
        currentframe = 0;
        samplesdone = 0;
        samplestoskip = 0;
        firstbyte = 3;  /* Take account of the little-endian 32-bit byte ordering */
    }

    /* Initialise the buffer */
    inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);

    /* The main decoding loop - we decode the frames a small chunk at a time */
    while (currentframe < ape_ctx.totalframes)
    {
frame_start:
        /* Calculate how many blocks there are in this frame */
        if (currentframe == (ape_ctx.totalframes - 1))
            nblocks = ape_ctx.finalframeblocks;
        else
            nblocks = ape_ctx.blocksperframe;

        ape_ctx.currentframeblocks = nblocks;

        /* Initialise the frame decoder */
        init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed);

        ci->advance_buffer(bytesconsumed);
        inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);

        /* Decode the frame a chunk at a time */
        while (nblocks > 0)
        {
            ci->yield();
            if (ci->stop_codec || ci->new_track) {
                goto done;
            }

            /* Deal with any pending seek requests */
            if (ci->seek_time) 
            {
                if (ape_calc_seekpos(&ape_ctx,
                    ((ci->seek_time-1)/10) * (ci->id3->frequency/100),
                    &currentframe,
                    &newfilepos,
                    &samplestoskip))
                {
                    samplesdone = currentframe * ape_ctx.blocksperframe;

                    /* APE's bytestream is weird... */
                    firstbyte = 3 - (newfilepos & 3);
                    newfilepos &= ~3;

                    ci->seek_buffer(newfilepos);
                    inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);

                    ci->seek_complete();
                    goto frame_start;  /* Sorry... */
                }
                ci->seek_complete();
            }

            blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);

            if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte,
                                    &bytesconsumed,
                                    decoded0, decoded1,
                                    blockstodecode)) < 0)
            {
                /* Frame decoding error, abort */
                LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res);
                retval = CODEC_ERROR;
                goto done;
            }

            ci->yield();

            if (samplestoskip > 0) {
                if (samplestoskip < blockstodecode) {
                    ci->pcmbuf_insert(decoded0 + samplestoskip, 
                                      decoded1 + samplestoskip, 
                                      blockstodecode - samplestoskip);
                    samplestoskip = 0;
                } else {
                    samplestoskip -= blockstodecode;
                }
            } else {
                ci->pcmbuf_insert(decoded0, decoded1, blockstodecode);
            }
        
            samplesdone += blockstodecode;

            if (!samplestoskip) {
                /* Update the elapsed-time indicator */
                elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
                ci->set_elapsed(elapsedtime);
            }

            ci->advance_buffer(bytesconsumed);
            inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);

            /* Decrement the block count */
            nblocks -= blockstodecode;
        }

        currentframe++;
    }

done:
    LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone);

    if (ci->request_next_track())
        goto next_track;

exit:
    return retval;
}
コード例 #24
0
ファイル: aiff.c プロジェクト: realtsiry/rockbox4linux
enum codec_status codec_main(void)
{
    int status = CODEC_OK;
    struct pcm_format format;
    uint32_t bytesdone, decodedsamples;
    uint32_t num_sample_frames = 0;
    size_t n;
    int bufcount;
    int endofstream;
    unsigned char *buf;
    uint8_t *aifbuf;
    uint32_t offset2snd = 0;
    off_t firstblockposn;     /* position of the first block in file */
    bool is_aifc = false;
    const struct pcm_codec *codec;
    uint32_t size;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
  
next_track:
    if (codec_init()) {
        status = CODEC_ERROR;
        goto exit;
    }

    while (!*ci->taginfo_ready && !ci->stop_codec)
        ci->sleep(1);

    codec_set_replaygain(ci->id3);
    
    /* Need to save offset for later use (cleared indirectly by advance_buffer) */
    bytesdone = ci->id3->offset;

    /* assume the AIFF header is less than 1024 bytes */
    buf = ci->request_buffer(&n, 1024);
    if (n < 54) {
        status = CODEC_ERROR;
        goto done;
    }

    if (memcmp(buf, "FORM", 4) != 0)
    {
        DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]);
        status = CODEC_ERROR;
        goto done;
    }
    if (memcmp(&buf[8], "AIFF", 4) == 0)
        is_aifc = false;
    else if (memcmp(&buf[8], "AIFC", 4) == 0)
        is_aifc = true;
    else
    {
        DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]);
        status = CODEC_ERROR;
        goto done;
    }

    buf += 12;
    n -= 12;

    ci->memset(&format, 0, sizeof(struct pcm_format));
    format.is_signed = true;
    format.is_little_endian = false;

    decodedsamples = 0;
    codec = 0;

    /* read until 'SSND' chunk, which typically is last */
    while (format.numbytes == 0 && n >= 8)
    {
        /* chunkSize */
        size = ((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]);
        if (memcmp(buf, "COMM", 4) == 0) {
            if ((!is_aifc && size < 18) || (is_aifc && size < 22))
            {
                DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n",
                       (unsigned long)size, (is_aifc)?22:18);
                status = CODEC_ERROR;
                goto done;
            }
            /* num_channels */
            format.channels = ((buf[8]<<8)|buf[9]);
            /* num_sample_frames */
            num_sample_frames = ((buf[10]<<24)|(buf[11]<<16)|(buf[12]<<8)
                                |buf[13]);
            /* sample_size */
            format.bitspersample = ((buf[14]<<8)|buf[15]);
            /* sample_rate (don't use last 4 bytes, only integer fs) */
            if (buf[16] != 0x40) {
                DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n");
                status = CODEC_ERROR;
                goto done;
            }
            format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
            format.samplespersec >>= (16 + 14 - buf[17]);
            /* compressionType (AIFC only) */
            if (is_aifc)
            {
                format.formattag = (buf[26]<<24)|(buf[27]<<16)|(buf[28]<<8)|buf[29];

                /*
                 * aiff's sample_size is uncompressed sound data size.
                 * But format.bitspersample is compressed sound data size.
                 */
                if (format.formattag == AIFC_FORMAT_ALAW ||
                    format.formattag == AIFC_FORMAT_MULAW)
                    format.bitspersample = 8;
                else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM)
                    format.bitspersample = 4;
            }
            else
                format.formattag = AIFC_FORMAT_PCM;
            /* calc average bytes per second */
            format.avgbytespersec = format.samplespersec*format.channels*format.bitspersample/8;
        } else if (memcmp(buf, "SSND", 4)==0) {
            if (format.bitspersample == 0) {
                DEBUGF("CODEC_ERROR: unsupported chunk order\n");
                status = CODEC_ERROR;
                goto done;
            }
            /* offset2snd */
            offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11];
            /* block_size */
            format.blockalign = ((buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]) >> 3;
            if (format.blockalign == 0)
                format.blockalign = format.channels * format.bitspersample >> 3;
            format.numbytes = size - 8 - offset2snd;
            size = 8 + offset2snd; /* advance to the beginning of data */
        } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) {
コード例 #25
0
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    uint32_t elapsedtime;
    int retval;
    asf_waveformatex_t wfx;     /* Holds the stream properties */
    size_t resume_offset;
    int res;                    /* Return values from asf_read_packet() and decode_packet() */
    uint8_t* audiobuf;          /* Pointer to the payload of one wma pro packet */
    int audiobufsize;           /* Payload size */
    int packetlength = 0;       /* Logical packet size (minus the header size) */          
    int outlen = 0;             /* Number of bytes written to the output buffer */
    int pktcnt = 0;             /* Count of the packets played */

    /* Generic codec initialisation */
    ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
    

next_track:
    retval = CODEC_OK;

    /* Wait for the metadata to be read */
    if (codec_wait_taginfo() != 0)
        goto done;

    /* Remember the resume position */
    resume_offset = ci->id3->offset;
restart_track:
    retval = CODEC_OK;

    if (codec_init()) {
        LOGF("(WMA Voice) Error: Error initialising codec\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Copy the format metadata we've stored in the id3 TOC field.  This
       saves us from parsing it again here. */
    memcpy(&wfx, ci->id3->toc, sizeof(wfx));
    memset(&avctx, 0, sizeof(AVCodecContext));
    memset(&avpkt, 0, sizeof(AVPacket));
    
    ci->configure(DSP_SWITCH_FREQUENCY, wfx.rate);
    ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
                  STEREO_MONO : STEREO_INTERLEAVED);
    codec_set_replaygain(ci->id3);
    
    /* Initialise the AVCodecContext */
    init_codec_ctx(&avctx, &wfx);

    if (wmavoice_decode_init(&avctx) < 0) {
        LOGF("(WMA Voice) Error: Unsupported or corrupt file\n");
        retval = CODEC_ERROR;
        goto done;
    }

    /* Now advance the file position to the first frame */
    ci->seek_buffer(ci->id3->first_frame_offset);
    
    elapsedtime = 0;
    resume_offset = 0;
    
    /* The main decoding loop */

    while (pktcnt < wfx.numpackets)
    {
        ci->yield();
        if (ci->stop_codec || ci->new_track) {
            goto done;
        }
        
        /* Deal with any pending seek requests */
        if (ci->seek_time){

            if (ci->seek_time == 1) {
                ci->seek_complete();
                goto restart_track; /* Pretend you never saw this... */
            }

            elapsedtime = asf_seek(ci->seek_time, &wfx);
            if (elapsedtime < 1){
                ci->seek_complete();
                goto next_track;
            }

            ci->set_elapsed(elapsedtime);
            ci->seek_complete();
        }
        
new_packet:
        res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);

        if (res < 0) {
            LOGF("(WMA Voice) read_packet error %d\n",res);
            goto done;
        } else {
            avpkt.data = audiobuf;
            avpkt.size = audiobufsize;
            pktcnt++;
            
            while(avpkt.size > 0)
            {
                /* wmavoice_decode_packet checks for the output buffer size to 
                   avoid overflows */
                outlen = BUFSIZE*sizeof(int32_t);

                res = wmavoice_decode_packet(&avctx, decoded, &outlen, &avpkt);
                if(res < 0) {
                    LOGF("(WMA Voice) Error: decode_packet returned %d", res);
                    if(res == ERROR_WMAPRO_IN_WMAVOICE){
                    /* Just skip this packet */
                        ci->advance_buffer(packetlength);
                        goto new_packet;    
                    }
                    else
                        goto done;
                }
                avpkt.data += res;
                avpkt.size -= res;
                if(outlen) {
                    ci->yield ();
                    outlen /= sizeof(int32_t);
                    ci->pcmbuf_insert(decoded, NULL, outlen);
                    elapsedtime += outlen*10/(wfx.rate/100);
                    ci->set_elapsed(elapsedtime);
                    ci->yield ();
                }
            }

        }

        /* Advance to the next logical packet */
        ci->advance_buffer(packetlength);
    }

done:
    if (ci->request_next_track())
        goto next_track;
    
    return retval;
}
コード例 #26
0
ファイル: tta.c プロジェクト: 4nykey/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    tta_info info;
    unsigned int decodedsamples;
    int endofstream;
    int new_pos = 0;
    int sample_count;
    intptr_t param;
  
    if (codec_init())
    {
        DEBUGF("codec_init() error\n");
        return CODEC_ERROR;
    }

    ci->seek_buffer(0);

    if (set_tta_info(&info) < 0 || player_init(&info) < 0)
        return CODEC_ERROR;

    codec_set_replaygain(ci->id3);

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    if (info.NCH == 2) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
    } else if (info.NCH == 1) {
        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
    } else {
        DEBUGF("CODEC_ERROR: more than 2 channels\n");
        player_stop();
        return CODEC_ERROR;
    }

    /* The main decoder loop */
    decodedsamples = 0;
    endofstream = 0;

    if (ci->id3->offset > 0)
    {
        /* Need to save offset for later use (cleared indirectly by advance_buffer) */
        new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
        if (new_pos >= 0)
            decodedsamples = new_pos;
    }

    ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);

    while (!endofstream)
    {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME)
        {
            new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME);
            if (new_pos >= 0)
            {
                decodedsamples = new_pos;
            }

            ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
            ci->seek_complete();
        }

        sample_count = get_samples(samples);
        if (sample_count < 0)
            break;
 
        ci->pcmbuf_insert(samples, NULL, sample_count);
        decodedsamples += sample_count;
        if (decodedsamples >= info.DATALENGTH)
            endofstream = 1;
        ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
    }

    player_stop();
    return CODEC_OK;
}
コード例 #27
0
ファイル: a52.c プロジェクト: claymodel/rockbox
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    size_t n;
    unsigned char *filebuf;
    int sample_loc;
    int retval;

    /* Generic codec initialisation */
    ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
    ci->configure(DSP_SET_SAMPLE_DEPTH, 28);

next_track:
    retval = CODEC_OK;

    if (codec_init()) {
        retval = CODEC_ERROR;
        goto exit;
    }

    if (codec_wait_taginfo() != 0)
        goto request_next_track;

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);
    
    /* Intialise the A52 decoder and check for success */
    state = a52_init(0);

    /* The main decoding loop */
    if (ci->id3->offset) {
        if (ci->seek_buffer(ci->id3->offset)) {
            samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
                A52_SAMPLESPERFRAME;
            ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
        }
    }
    else {
        samplesdone = 0;
    }

    while (1) {
        if (ci->stop_codec || ci->new_track)
            break;

        if (ci->seek_time) {
            sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency;

            if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
                samplesdone = sample_loc;
                ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
            }
            ci->seek_complete();
        }

        filebuf = ci->request_buffer(&n, BUFFER_SIZE);

        if (n == 0) /* End of Stream */
            break;
  
        a52_decode_data(filebuf, filebuf + n);
        ci->advance_buffer(n);
    }

request_next_track:
    if (ci->request_next_track())
        goto next_track;

exit:
    a52_free(state);
    return retval;
}
コード例 #28
0
ファイル: flac.c プロジェクト: BackupTheBerlios/bimmerbox
/* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api)
{
    struct codec_api* ci = api;
    FLAC__SeekableStreamDecoder* flacDecoder;
    FLAC__uint64 offset;

    TEST_CODEC_API(ci);

#ifndef SIMULATOR
    ci->memcpy(iramstart, iramcopy, iramend-iramstart);
#endif

    ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
    ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
    ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*1024));

    ci->configure(CODEC_DSP_ENABLE, (bool *)true);
    ci->configure(DSP_DITHER, (bool *)false);
    ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
    ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
  
next_track:
    metadata_length = 0;
    seek_table = NULL;
    stream_info = NULL;

    if (codec_init(api)) {
        return CODEC_ERROR;
    }

    while (!ci->taginfo_ready)
        ci->yield();
    
    ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
    codec_set_replaygain(ci->id3);
  
    /* Create a decoder instance */
    flacDecoder = FLAC__seekable_stream_decoder_new();

    /* Set up the decoder and the callback functions - this must be done before init */

    /* The following are required for stream_decoder and higher */
    FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci);
    FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler);
    FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler);
    FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler);
    FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler);
    FLAC__seekable_stream_decoder_set_metadata_respond_all(flacDecoder);

    /* The following are only for the seekable_stream_decoder */
    FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler);
    FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler);
    FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler);
    FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler);


    /* QUESTION: What do we do when the init fails? */
    if (FLAC__seekable_stream_decoder_init(flacDecoder)) {
        return CODEC_ERROR;
    }

    /* The first thing to do is to parse the metadata */
    FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder);

    if (ci->id3->offset && stream_info) {
        FLAC__uint64 sample;

        sample = find_sample_number(ci, ci->id3->offset - metadata_length);
        ci->advance_buffer(ci->id3->offset);
        FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample);
        FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset);
        ci->set_offset(offset);
        samplesdone = (uint32_t)sample;
        ci->set_elapsed(sample/(ci->id3->frequency/1000));
    } else {
        samplesdone = 0;
        ci->set_elapsed(0);
    }

    /* The main decoder loop */
    while (FLAC__seekable_stream_decoder_get_state(flacDecoder) != FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
        ci->yield();
        if (ci->stop_codec || ci->reload_codec) {
            break;
        }

        if (ci->seek_time) {
            int sample_loc;

            sample_loc = ci->seek_time/1000 * ci->id3->frequency;
            if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample_loc)) {
                samplesdone = sample_loc;
                ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
            }
            ci->seek_time = 0;
        }

        FLAC__seekable_stream_decoder_process_single(flacDecoder);
        FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset);
        ci->set_offset(offset);
    }

    /* Flush the libFLAC buffers */
    FLAC__seekable_stream_decoder_finish(flacDecoder);

    if (ci->request_next_track()) {
        if (stream_info) {
            FLAC__metadata_object_delete(stream_info);
        }
        if (seek_table) {
            FLAC__metadata_object_delete(seek_table);
        }
        metadata_length = 0;
        goto next_track;
    }

    return CODEC_OK;
}
コード例 #29
0
ファイル: asap.c プロジェクト: BurntBrunch/rockbox-fft
/* this is the codec entry point */
enum codec_status codec_main(void)
{
    int n_bytes;
    int song;
    int duration;
    char* module;
    int bytesPerSample =2;
    
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);
        
    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; 
    }    
    /* reset eleapsed */
    ci->set_elapsed(0);

    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);
    
    /* 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 */
                      
            /* seek to pos */
            ASAP_Seek(&asap,ci->seek_time);
            /* update elapsed */
            ci->set_elapsed(ci->seek_time);
            /* update bytes_done */
            bytes_done = ci->seek_time*44.1*2;    
            /* 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;
    }

    if (ci->request_next_track())
        goto next_track;
 
    return CODEC_OK;    
}
コード例 #30
0
ファイル: a52_rm.c プロジェクト: 4nykey/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    size_t n;
    uint8_t *filebuf;
    int consumed, packet_offset;
    int playback_on = -1;
    size_t resume_offset;
    intptr_t param;
    enum codec_command_action action = CODEC_ACTION_NULL;

    if (codec_init()) {
        return CODEC_ERROR;
    }

    resume_offset = ci->id3->offset;

    ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
    codec_set_replaygain(ci->id3);

    ci->seek_buffer(ci->id3->first_frame_offset);

    /* Intializations */
    state = a52_init(0);
    ci->memset(&rmctx,0,sizeof(RMContext)); 
    ci->memset(&pkt,0,sizeof(RMPacket));
    init_rm(&rmctx);

    samplesdone = 0;

    /* check for a mid-track resume and force a seek time accordingly */
    if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
        resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
        /* put number of subpackets to skip in resume_offset */
        resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
        param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
        action = CODEC_ACTION_SEEK_TIME;
    }
    else {
        /* Seek to the first packet */
        ci->set_elapsed(0);
        ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
    }

    /* The main decoding loop */
    while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) {
        if (action == CODEC_ACTION_NULL)
            action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate);
            ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE +
                            packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
            rmctx.audio_pkt_cnt = packet_offset;
            samplesdone = (rmctx.sample_rate/1000 * param);
            ci->set_elapsed(samplesdone/(frequency/1000));
            ci->seek_complete();
        }

        action = CODEC_ACTION_NULL;

        filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
        consumed = rm_get_packet(&filebuf, &rmctx, &pkt);

        if(consumed < 0 && playback_on != 0) {
            if(playback_on == -1) {
            /* Error only if packet-parsing failed and playback hadn't started */
                DEBUGF("rm_get_packet failed\n");
                return CODEC_ERROR;
            }
            else {
                break;
            }
        }

        playback_on = 1;
        a52_decode_data(filebuf, filebuf + rmctx.block_align);
        ci->advance_buffer(pkt.length);
    }

    return CODEC_OK;
}