Пример #1
0
static void
gst_speex_dec_reset (GstSpeexDec * dec)
{
  dec->packetno = 0;
  dec->frame_size = 0;
  dec->frame_duration = 0;
  dec->mode = NULL;
  free (dec->header);
  dec->header = NULL;
  speex_bits_destroy (&dec->bits);
  speex_bits_set_bit_buffer (&dec->bits, NULL, 0);

  gst_buffer_replace (&dec->streamheader, NULL);
  gst_buffer_replace (&dec->vorbiscomment, NULL);

  if (dec->stereo) {
    speex_stereo_state_destroy (dec->stereo);
    dec->stereo = NULL;
  }

  if (dec->state) {
    speex_decoder_destroy (dec->state);
    dec->state = NULL;
  }
}
Пример #2
0
int universal_speex_get_packet_samples(void          *handle,
                                       const uint8_t *pPacketData,
                                       unsigned       packetSize,
                                       unsigned      *pNumSamples,
                                       const struct RtpHeader* pRtpHeader)
{
   SpeexBits bits;
   int num_frames;
   struct speex_codec_data_decoder *pSpeexDec = 
      (struct speex_codec_data_decoder *)handle;
   assert(handle != NULL);

   /* Wrap data to speex_bits struct */
   speex_bits_set_bit_buffer(&bits, (void*)pPacketData, packetSize);

   /* Get number of frames */
   num_frames = speex_bits_get_num_frames(&bits);
   if (num_frames < 0)
   {
      return RPLG_CORRUPTED_DATA;
   }

   /* Return number of samples */
   *pNumSamples = num_frames * pSpeexDec->mNumSamplesPerFrame;
   return RPLG_SUCCESS;
}
/* Decode frames or stop if all have completed */
static enum voice_state voice_decode(struct voice_thread_data *td)
{
    if (!queue_empty(&voice_queue))
        return VOICE_STATE_MESSAGE;

    /* 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;
        }
        else
        {
            /* If all clips are done and not playing, force pcm playback. */
            voice_start_playback();
            return VOICE_STATE_MESSAGE;
        }
    }
    else
    {
        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);

        if (td->count > 0)
            return VOICE_STATE_BUFFER_INSERT;
    }

    return VOICE_STATE_DECODE;
}
Пример #4
0
static gboolean
gst_speex_enc_stop (GstAudioEncoder * benc)
{
  GstSpeexEnc *enc = GST_SPEEX_ENC (benc);

  GST_DEBUG_OBJECT (enc, "stop");
  enc->header_sent = FALSE;
  if (enc->state) {
    speex_encoder_destroy (enc->state);
    enc->state = NULL;
  }
  speex_bits_destroy (&enc->bits);
  speex_bits_set_bit_buffer (&enc->bits, NULL, 0);
  gst_tag_list_unref (enc->tags);
  enc->tags = NULL;

  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));

  return TRUE;
}
Пример #5
0
/* 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;
}
/* Voice thread message processing */
static enum voice_state voice_message(struct voice_thread_data *td)
{
    if (quiet_counter > 0)
        queue_wait_w_tmo(&voice_queue, &td->ev, HZ/10);
    else
        queue_wait(&voice_queue, &td->ev);

    switch (td->ev.id)
    {
    case Q_VOICE_PLAY:
        LOGFQUEUE("voice < Q_VOICE_PLAY");
        if (quiet_counter == 0)
        {
            /* Boost CPU now */
            trigger_cpu_boost();
        }
        else
        {
            /* Stop any clip still playing */
            voice_stop_playback();
        }

        quiet_counter = QUIET_COUNT;

        /* Copy the clip info */
        td->vi = *(struct voice_info *)td->ev.data;

        /* Be sure audio buffer is initialized */
        audio_restore_playback(AUDIO_WANT_VOICE);

        /* We need nothing more from the sending thread - let it run */
        queue_reply(&voice_queue, 1);

        /* Make audio play more softly and set delay to return to normal
           playback level */
        pcmbuf_soft_mode(true);

        /* Clean-start the decoder */
        td->st = speex_decoder_init(&speex_wb_mode);

        /* Make bit buffer use our own buffer */
        speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size);
        speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);

        return VOICE_STATE_DECODE;

    case SYS_TIMEOUT:
        if (voice_unplayed_frames())
        {
            /* Waiting for PCM to finish */
            break;
        }

        /* Drop through and stop the first time after clip runs out */
        if (quiet_counter-- != QUIET_COUNT)
        {
            if (quiet_counter <= 0)
                pcmbuf_soft_mode(false);

            break;
        }

        /* Fall-through */
    case Q_VOICE_STOP:
        LOGFQUEUE("voice < Q_VOICE_STOP");
        cancel_cpu_boost();
        voice_stop_playback();
        break;

    /* No default: no other message ids are sent */
    }

    return VOICE_STATE_MESSAGE;
}
Пример #7
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 */
Пример #8
0
/* Voice thread message processing */
static void voice_message(struct voice_thread_data *td)
{
    while (1)
    {
        switch (td->ev.id)
        {
        case Q_VOICE_PLAY:
            LOGFQUEUE("voice < Q_VOICE_PLAY");
            /* Put up a block for completion signal */
            voice_done = false;

            /* Copy the clip info */
            td->vi = *(struct voice_info *)td->ev.data;

            /* Be sure audio buffer is initialized */
            audio_restore_playback(AUDIO_WANT_VOICE);

            /* We need nothing more from the sending thread - let it run */
            queue_reply(&voice_queue, 1);

            if (td->state == TSTATE_STOPPED)
            {
                /* Boost CPU now */
                trigger_cpu_boost();
            }
            else if (!playback_is_playing())
            {
                /* Just voice, stop any clip still playing */
                pcmbuf_play_stop();
            }

            /* Clean-start the decoder */
            td->st = speex_decoder_init(&speex_wb_mode);

            /* Make bit buffer use our own buffer */
            speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size);
            speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);

            td->state = TSTATE_DECODE;
            return;

        case Q_VOICE_STOP:
            LOGFQUEUE("voice < Q_VOICE_STOP: %ld", td->ev.data);

            if (td->ev.data != 0 && !playback_is_playing())
            {
                /* If not playing, it's just voice so stop pcm playback */
                pcmbuf_play_stop();
            }

            /* Cancel boost */
            cancel_cpu_boost();

            td->state = TSTATE_STOPPED;
            voice_done = true;
            break;

        case Q_VOICE_STATE:
            LOGFQUEUE("voice < Q_VOICE_STATE");
            queue_reply(&voice_queue, td->state);

            if (td->state == TSTATE_STOPPED)
                break; /* Not in a playback state */

            return;

        default:
            /* Default messages get a reply and thread continues with no
             * state transition */
            LOGFQUEUE("voice < default");

            if (td->state == TSTATE_STOPPED)
                break;  /* Not in playback state */

            queue_reply(&voice_queue, 0);
            return;
        }

        queue_wait(&voice_queue, &td->ev);
    }
}
Пример #9
0
int universal_speex_decode(void* handle, const void* pCodedData, 
                          unsigned cbCodedPacketSize, void* pAudioBuffer, 
                          unsigned cbBufferSize, unsigned *pcbDecodedSize, 
                          const struct RtpHeader* pRtpHeader)
{
   SpeexBits bits;
   struct speex_codec_data_decoder *mpSpeexDec = 
      (struct speex_codec_data_decoder *)handle;
   assert(handle != NULL);

   if (mpSpeexDec->mNumSamplesPerFrame > cbBufferSize)
   {
      return RPLG_INVALID_ARGUMENT;
   }

   /* Reset number of decoded samples */
   *pcbDecodedSize = 0;

   /* Decode incoming packet if present. Do PLC if no packet. */
   if (pCodedData)
   {
      /* Prepare data for Speex decoder */
      speex_bits_set_bit_buffer(&bits,(char*)pCodedData, cbCodedPacketSize);

      /* Decode while there are something to decode and enough space
      * for decoded data. */
      while (cbBufferSize >= mpSpeexDec->mNumSamplesPerFrame &&
             (speex_bits_remaining(&bits) > 0))
      {
         int res;

         /* Decode frame */
         res = speex_decode_int(mpSpeexDec->mpDecoderState, &bits,
                                ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize));
         if (res == 0)
         {
            /* Update number of decoded and available samples on success */
            *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame;
            cbBufferSize -= mpSpeexDec->mNumSamplesPerFrame;
         }
         else
         {
            /* If it's the end of the stream or corrupted stream just return */
            break;
         }
      }
   }
   else
   {
      int res;

      /* Do PLC */
      res = speex_decode_int(mpSpeexDec->mpDecoderState, NULL,
                             ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize));
      if (res == 0)
      {
         /* Update number of decoded and available samples on success */
         *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame;
      }
      else
      {
         /* This mustn't happen for lost packet, but who knows... */
         return RPLG_FAILED;
      }
   }

   return RPLG_SUCCESS;
}