Пример #1
0
static void codec_pcmbuf_insert_callback(
    const void *ch1, const void *ch2, int count)
{
    const char *src[2] = { ch1, ch2 };

    while (count > 0)
    {
        int out_count = dsp_output_count(ci.dsp, count);
        int inp_count;
        char *dest;

        while (1)
        {
            if ((dest = pcmbuf_request_buffer(&out_count)) != NULL)
                break;

            cancel_cpu_boost();

            /* It will be awhile before space is available but we want
               "instant" response to any message */
            queue_wait_w_tmo(&codec_queue, NULL, HZ/20);

            if (!queue_empty(&codec_queue) &&
                    codec_check_queue__have_msg() < 0)
                return;
        }

        /* Get the real input_size for output_size bytes, guarding
         * against resampling buffer overflows. */
        inp_count = dsp_input_count(ci.dsp, out_count);

        if (inp_count <= 0)
            return;

        /* Input size has grown, no error, just don't write more than length */
        if (inp_count > count)
            inp_count = count;

        out_count = dsp_process(ci.dsp, dest, src, inp_count);

        if (out_count <= 0)
            return;

        pcmbuf_write_complete(out_count);

        count -= inp_count;
    }
}
/* Process the PCM samples in the DSP and send out for mixing */
static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
{
    if (!queue_empty(&voice_queue))
        return VOICE_STATE_MESSAGE;

    char *dest = (char *)voice_buf_get();

    if (dest != NULL)
    {
        voice_buf_commit(dsp_process(td->dsp, dest, td->src, td->count)
                         * sizeof (int32_t));
        return VOICE_STATE_DECODE;
    }

    sleep(0);
    return VOICE_STATE_BUFFER_INSERT;
}
Пример #3
0
static void codec_pcmbuf_insert_callback(
        const void *ch1, const void *ch2, int count)
{
    const char *src[2] = { ch1, ch2 };

    while (count > 0)
    {
        int out_count = dsp_output_count(ci.dsp, count);
        int inp_count;
        char *dest;

        /* Prevent audio from a previous track from playing */
        if (ci.new_track || ci.stop_codec)
            return;

        while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
        {
            cancel_cpu_boost();
            sleep(1);
            if (ci.seek_time || ci.new_track || ci.stop_codec)
                return;
        }

        /* Get the real input_size for output_size bytes, guarding
         * against resampling buffer overflows. */
        inp_count = dsp_input_count(ci.dsp, out_count);

        if (inp_count <= 0)
            return;

        /* Input size has grown, no error, just don't write more than length */
        if (inp_count > count)
            inp_count = count;

        out_count = dsp_process(ci.dsp, dest, src, inp_count);

        if (out_count <= 0)
            return;

        pcmbuf_write_complete(out_count);

        count -= inp_count;
    }
} /* codec_pcmbuf_insert_callback */
Пример #4
0
static void ci_pcmbuf_insert(const void *ch1, const void *ch2, int count)
{
    num_output_samples += count;

    if (use_dsp) {
        struct dsp_buffer src;
        src.remcount = count;
        src.pin[0] = ch1;
        src.pin[1] = ch2;
        src.proc_mask = 0;
        while (1) {
            int out_count = MAX(count, 512);
            int16_t buf[2 * out_count];
            struct dsp_buffer dst;

            dst.remcount = 0;
            dst.p16out = buf;
            dst.bufcount = out_count;

            dsp_process(ci.dsp, &src, &dst);

            if (dst.remcount > 0) {
                if (mode == MODE_WRITE)
                    write_pcm(buf, dst.remcount);
                else if (mode == MODE_PLAY)
                    playback_pcm(buf, dst.remcount);
            } else if (src.remcount <= 0) {
                break;
            }
        }
    } else {
        /* Convert to 32-bit interleaved. */
        count *= format.channels;
        int i;
        int32_t buf[count];
        if (format.depth > 16) {
            if (format.stereo_mode == STEREO_NONINTERLEAVED) {
                for (i = 0; i < count; i += 2) {
                    buf[i+0] = ((int32_t*)ch1)[i/2];
                    buf[i+1] = ((int32_t*)ch2)[i/2];
                }
            } else {
                memcpy(buf, ch1, sizeof(buf));
            }
        } else {
            if (format.stereo_mode == STEREO_NONINTERLEAVED) {
                for (i = 0; i < count; i += 2) {
                    buf[i+0] = ((int16_t*)ch1)[i/2];
                    buf[i+1] = ((int16_t*)ch2)[i/2];
                }
            } else {
                for (i = 0; i < count; i++) {
                    buf[i] = ((int16_t*)ch1)[i];
                }
            }
        }

        if (mode == MODE_WRITE)
            write_pcm_raw(buf, count);
    }

    perform_config();
}
Пример #5
0
/* Voice thread entrypoint */
static void voice_thread(void)
{
    struct voice_thread_data td;

    voice_data_init(&td);

    /* audio thread will only set this once after it finished the final
     * audio hardware init so this little construct is safe - even
     * cross-core. */
    while (!audio_is_thread_ready())
        sleep(0);

    goto message_wait;

    while (1)
    {
        td.state = TSTATE_DECODE;

        if (!queue_empty(&voice_queue))
        {
        message_wait:
            queue_wait(&voice_queue, &td.ev);

        message_process:
            voice_message(&td);

            /* Branch to initial start point or branch back to previous
             * operation if interrupted by a message */
            switch (td.state)
            {
            case TSTATE_DECODE:        goto voice_decode;
            case TSTATE_BUFFER_INSERT: goto buffer_insert;
            default:                   goto message_wait;
            }
        }

    voice_decode:
        /* Decode the data */
        if (speex_decode_int(td.st, &td.bits, voice_output_buf) < 0)
        {
            /* End of stream or error - get next clip */
            td.vi.size = 0;

            if (td.vi.get_more != NULL)
                td.vi.get_more(&td.vi.start, &td.vi.size);

            if (td.vi.start != NULL && (ssize_t)td.vi.size > 0)
            {
                /* Make bit buffer use our own buffer */
                speex_bits_set_bit_buffer(&td.bits, td.vi.start, td.vi.size);
                /* Don't skip any samples when we're stringing clips together */
                td.lookahead = 0;

                /* Paranoid check - be sure never to somehow get stuck in a
                 * loop without listening to the queue */
                yield();

                if (!queue_empty(&voice_queue))
                    goto message_wait;
                else
                    goto voice_decode;
            }

            /* If all clips are done and not playing, force pcm playback. */
            if (!pcm_is_playing())
                pcmbuf_play_start();

            /* Synthesize a stop request */
            /* NOTE: We have no way to know when the pcm data placed in the
             * buffer is actually consumed and playback has reached the end
             * so until the info is available or inferred somehow, this will
             * not be accurate and the stopped signal will come too soon.
             * ie. You may not hear the "Shutting Down" splash even though
             * it waits for voice to stop. */
            td.ev.id = Q_VOICE_STOP;
            td.ev.data = 0; /* Let PCM drain by itself */
            yield();
            goto message_process;
        }

        yield();

        /* Output the decoded frame */
        td.count = VOICE_FRAME_SIZE - td.lookahead;
        td.src[0] = (const char *)&voice_output_buf[td.lookahead];
        td.src[1] = NULL;
        td.lookahead -= MIN(VOICE_FRAME_SIZE, td.lookahead);

    buffer_insert:
        /* Process the PCM samples in the DSP and send out for mixing */
        td.state = TSTATE_BUFFER_INSERT;

        while (td.count > 0)
        {
            int out_count = dsp_output_count(td.dsp, td.count);
            int inp_count;
            char *dest;

            while (1)
            {
                if (!queue_empty(&voice_queue))
                    goto message_wait;

                if ((dest = pcmbuf_request_voice_buffer(&out_count)) != NULL)
                    break;

                yield();
            }

            /* Get the real input_size for output_size bytes, guarding
             * against resampling buffer overflows. */
            inp_count = dsp_input_count(td.dsp, out_count);

            if (inp_count <= 0)
                break;

            /* Input size has grown, no error, just don't write more than
             * length */
            if (inp_count > td.count)
                inp_count = td.count;

            out_count = dsp_process(td.dsp, dest, td.src, inp_count);

            if (out_count <= 0)
                break;

            pcmbuf_write_voice_complete(out_count);
            td.count -= inp_count;
        }

        yield();
    } /* end while */
} /* voice_thread */