示例#1
0
int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
{
   void *silk_dec;
   CELTDecoder *celt_dec;
   int ret, silkDecSizeBytes;

   if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
    || (channels!=1&&channels!=2))
      return OPUS_BAD_ARG;

   OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
   /* Initialize SILK encoder */
   ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
   if (ret)
      return OPUS_INTERNAL_ERROR;

   silkDecSizeBytes = align(silkDecSizeBytes);
   st->silk_dec_offset = align(sizeof(OpusDecoder));
   st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
   silk_dec = (char*)st+st->silk_dec_offset;
   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
   st->stream_channels = st->channels = channels;

   st->Fs = Fs;
   st->DecControl.API_sampleRate = st->Fs;
   st->DecControl.nChannelsAPI      = st->channels;
   st->arch = opus_select_arch();

   /* Reset decoder */
   ret = silk_InitDecoder( silk_dec );
   if(ret)return OPUS_INTERNAL_ERROR;

   /* Initialize CELT decoder */
   ret = celt_decoder_init(celt_dec, Fs, channels);
   if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;

   celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));

   st->prev_mode = 0;
   st->frame_size = Fs/400;
   return OPUS_OK;
}
示例#2
0
int opus_decoder_ctl(OpusDecoder *st, int request, ...)
{
    int ret = OPUS_OK;
    va_list ap;
    void *silk_dec;
    CELTDecoder *celt_dec;

    silk_dec = (char*)st+st->silk_dec_offset;
    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);


    va_start(ap, request);

    switch (request)
    {
    case OPUS_GET_BANDWIDTH_REQUEST:
    {
        opus_int32 *value = va_arg(ap, opus_int32*);
        if (!value)
        {
            goto bad_arg;
        }
        *value = st->bandwidth;
    }
    break;
    case OPUS_GET_FINAL_RANGE_REQUEST:
    {
        opus_uint32 *value = va_arg(ap, opus_uint32*);
        if (!value)
        {
            goto bad_arg;
        }
        *value = st->rangeFinal;
    }
    break;
    case OPUS_RESET_STATE:
    {
        OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
                   sizeof(OpusDecoder)-
                   ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));

        celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
        silk_InitDecoder( silk_dec );
        st->stream_channels = st->channels;
        st->frame_size = st->Fs/400;
    }
    break;
    case OPUS_GET_SAMPLE_RATE_REQUEST:
    {
        opus_int32 *value = va_arg(ap, opus_int32*);
        if (!value)
        {
            goto bad_arg;
        }
        *value = st->Fs;
    }
    break;
    case OPUS_GET_PITCH_REQUEST:
    {
        opus_int32 *value = va_arg(ap, opus_int32*);
        if (!value)
        {
            goto bad_arg;
        }
        if (st->prev_mode == MODE_CELT_ONLY)
            celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
        else
            *value = st->DecControl.prevPitchLag;
    }
    break;
    case OPUS_GET_GAIN_REQUEST:
    {
        opus_int32 *value = va_arg(ap, opus_int32*);
        if (!value)
        {
            goto bad_arg;
        }
        *value = st->decode_gain;
    }
    break;
    case OPUS_SET_GAIN_REQUEST:
    {
        opus_int32 value = va_arg(ap, opus_int32);
        if (value<-32768 || value>32767)
        {
            goto bad_arg;
        }
        st->decode_gain = value;
    }
    break;
    case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
    {
        opus_uint32 *value = va_arg(ap, opus_uint32*);
        if (!value)
        {
            goto bad_arg;
        }
        *value = st->last_packet_duration;
    }
    break;
    default:
        /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
        ret = OPUS_UNIMPLEMENTED;
        break;
    }

    va_end(ap);
    return ret;
bad_arg:
    va_end(ap);
    return OPUS_BAD_ARG;
}
示例#3
0
static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                             opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
    void *silk_dec;
    CELTDecoder *celt_dec;
    int i, silk_ret=0, celt_ret=0;
    ec_dec dec;
    opus_int32 silk_frame_size;
    int pcm_silk_size;
    VARDECL(opus_int16, pcm_silk);
    int pcm_transition_silk_size;
    VARDECL(opus_val16, pcm_transition_silk);
    int pcm_transition_celt_size;
    VARDECL(opus_val16, pcm_transition_celt);
    opus_val16 *pcm_transition=NULL;
    int redundant_audio_size;
    VARDECL(opus_val16, redundant_audio);

    int audiosize;
    int mode;
    int transition=0;
    int start_band;
    int redundancy=0;
    int redundancy_bytes = 0;
    int celt_to_silk=0;
    int c;
    int F2_5, F5, F10, F20;
    const opus_val16 *window;
    opus_uint32 redundant_rng = 0;
    int celt_accum;
    ALLOC_STACK;

    silk_dec = (char*)st+st->silk_dec_offset;
    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
    F20 = st->Fs/50;
    F10 = F20>>1;
    F5 = F10>>1;
    F2_5 = F5>>1;
    if (frame_size < F2_5)
    {
        RESTORE_STACK;
        return OPUS_BUFFER_TOO_SMALL;
    }
    /* Limit frame_size to avoid excessive stack allocations. */
    frame_size = IMIN(frame_size, st->Fs/25*3);
    /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
    if (len<=1)
    {
        data = NULL;
        /* In that case, don't conceal more than what the ToC says */
        frame_size = IMIN(frame_size, st->frame_size);
    }
    if (data != NULL)
    {
        audiosize = st->frame_size;
        mode = st->mode;
        ec_dec_init(&dec,(unsigned char*)data,len);
    } else {
        audiosize = frame_size;
        mode = st->prev_mode;

        if (mode == 0)
        {
            /* If we haven't got any packet yet, all we can do is return zeros */
            for (i=0; i<audiosize*st->channels; i++)
                pcm[i] = 0;
            RESTORE_STACK;
            return audiosize;
        }

        /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
           10, or 20 (e.g. 12.5 or 30 ms). */
        if (audiosize > F20)
        {
            do {
                int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
                if (ret<0)
                {
                    RESTORE_STACK;
                    return ret;
                }
                pcm += ret*st->channels;
                audiosize -= ret;
            } while (audiosize > 0);
            RESTORE_STACK;
            return frame_size;
        } else if (audiosize < F20)
        {
            if (audiosize > F10)
                audiosize = F10;
            else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
                audiosize = F5;
        }
    }

    /* In fixed-point, we can tell CELT to do the accumulation on top of the
       SILK PCM buffer. This saves some stack space. */
#ifdef FIXED_POINT
    celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10);
#else
    celt_accum = 0;
#endif

    pcm_transition_silk_size = ALLOC_NONE;
    pcm_transition_celt_size = ALLOC_NONE;
    if (data!=NULL && st->prev_mode > 0 && (
                (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
                || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
       )
    {
        transition = 1;
        /* Decide where to allocate the stack memory for pcm_transition */
        if (mode == MODE_CELT_ONLY)
            pcm_transition_celt_size = F5*st->channels;
        else
            pcm_transition_silk_size = F5*st->channels;
    }
    ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
    if (transition && mode == MODE_CELT_ONLY)
    {
        pcm_transition = pcm_transition_celt;
        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
    }
    if (audiosize > frame_size)
    {
        /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
        RESTORE_STACK;
        return OPUS_BAD_ARG;
    } else {
        frame_size = audiosize;
    }

    /* Don't allocate any memory when in CELT-only mode */
    pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
    ALLOC(pcm_silk, pcm_silk_size, opus_int16);

    /* SILK processing */
    if (mode != MODE_CELT_ONLY)
    {
        int lost_flag, decoded_samples;
        opus_int16 *pcm_ptr;
#ifdef FIXED_POINT
        if (celt_accum)
            pcm_ptr = pcm;
        else
#endif
            pcm_ptr = pcm_silk;

        if (st->prev_mode==MODE_CELT_ONLY)
            silk_InitDecoder( silk_dec );

        /* The SILK PLC cannot produce frames of less than 10 ms */
        st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);

        if (data != NULL)
        {
            st->DecControl.nChannelsInternal = st->stream_channels;
            if( mode == MODE_SILK_ONLY ) {
                if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
                    st->DecControl.internalSampleRate = 8000;
                } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
                    st->DecControl.internalSampleRate = 12000;
                } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
                    st->DecControl.internalSampleRate = 16000;
                } else {
                    st->DecControl.internalSampleRate = 16000;
                    silk_assert( 0 );
                }
            } else {
                /* Hybrid mode */
                st->DecControl.internalSampleRate = 16000;
            }
        }

        lost_flag = data == NULL ? 1 : 2 * decode_fec;
        decoded_samples = 0;
        do {
            /* Call SILK decoder */
            int first_frame = decoded_samples == 0;
            silk_ret = silk_Decode( silk_dec, &st->DecControl,
                                    lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size );
            if( silk_ret ) {
                if (lost_flag) {
                    /* PLC failure should not be fatal */
                    silk_frame_size = frame_size;
                    for (i=0; i<frame_size*st->channels; i++)
                        pcm_ptr[i] = 0;
                } else {
                    RESTORE_STACK;
                    return OPUS_INTERNAL_ERROR;
                }
            }
            pcm_ptr += silk_frame_size * st->channels;
            decoded_samples += silk_frame_size;
        } while( decoded_samples < frame_size );
    }

    start_band = 0;
    if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
            && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
    {
        /* Check if we have a redundant 0-8 kHz band */
        if (mode == MODE_HYBRID)
            redundancy = ec_dec_bit_logp(&dec, 12);
        else
            redundancy = 1;
        if (redundancy)
        {
            celt_to_silk = ec_dec_bit_logp(&dec, 1);
            /* redundancy_bytes will be at least two, in the non-hybrid
               case due to the ec_tell() check above */
            redundancy_bytes = mode==MODE_HYBRID ?
                               (opus_int32)ec_dec_uint(&dec, 256)+2 :
                               len-((ec_tell(&dec)+7)>>3);
            len -= redundancy_bytes;
            /* This is a sanity check. It should never happen for a valid
               packet, so the exact behaviour is not normative. */
            if (len*8 < ec_tell(&dec))
            {
                len = 0;
                redundancy_bytes = 0;
                redundancy = 0;
            }
            /* Shrink decoder because of raw bits */
            dec.storage -= redundancy_bytes;
        }
    }
    if (mode != MODE_CELT_ONLY)
        start_band = 17;

    {
        int endband=21;

        switch(st->bandwidth)
        {
        case OPUS_BANDWIDTH_NARROWBAND:
            endband = 13;
            break;
        case OPUS_BANDWIDTH_MEDIUMBAND:
        case OPUS_BANDWIDTH_WIDEBAND:
            endband = 17;
            break;
        case OPUS_BANDWIDTH_SUPERWIDEBAND:
            endband = 19;
            break;
        case OPUS_BANDWIDTH_FULLBAND:
            endband = 21;
            break;
        }
        celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband));
        celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels));
    }

    if (redundancy)
    {
        transition = 0;
        pcm_transition_silk_size=ALLOC_NONE;
    }

    ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);

    if (transition && mode != MODE_CELT_ONLY)
    {
        pcm_transition = pcm_transition_silk;
        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
    }

    /* Only allocation memory for redundancy if/when needed */
    redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
    ALLOC(redundant_audio, redundant_audio_size, opus_val16);

    /* 5 ms redundant frame for CELT->SILK*/
    if (redundancy && celt_to_silk)
    {
        celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
        celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
                            redundant_audio, F5, NULL, 0);
        celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
    }

    /* MUST be after PLC */
    celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));

    if (mode != MODE_SILK_ONLY)
    {
        int celt_frame_size = IMIN(F20, frame_size);
        /* Make sure to discard any previous CELT state */
        if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
            celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
        /* Decode CELT */
        celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data,
                                       len, pcm, celt_frame_size, &dec, celt_accum);
    } else {
        unsigned char silence[2] = {0xFF, 0xFF};
        if (!celt_accum)
        {
            for (i=0; i<frame_size*st->channels; i++)
                pcm[i] = 0;
        }
        /* For hybrid -> SILK transitions, we let the CELT MDCT
           do a fade-out by decoding a silence frame */
        if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
        {
            celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
            celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
        }
    }

    if (mode != MODE_CELT_ONLY && !celt_accum)
    {
#ifdef FIXED_POINT
        for (i=0; i<frame_size*st->channels; i++)
            pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i]));
#else
        for (i=0; i<frame_size*st->channels; i++)
            pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
#endif
    }

    {
        const CELTMode *celt_mode;
        celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
        window = celt_mode->window;
    }

    /* 5 ms redundant frame for SILK->CELT */
    if (redundancy && !celt_to_silk)
    {
        celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
        celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));

        celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
        celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
        smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
                    pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
    }
    if (redundancy && celt_to_silk)
    {
        for (c=0; c<st->channels; c++)
        {
            for (i=0; i<F2_5; i++)
                pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
        }
        smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
                    pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
    }
    if (transition)
    {
        if (audiosize >= F5)
        {
            for (i=0; i<st->channels*F2_5; i++)
                pcm[i] = pcm_transition[i];
            smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
                        pcm+st->channels*F2_5, F2_5,
                        st->channels, window, st->Fs);
        } else {
            /* Not enough time to do a clean transition, but we do it anyway
               This will not preserve amplitude perfectly and may introduce
               a bit of temporal aliasing, but it shouldn't be too bad and
               that's pretty much the best we can do. In any case, generating this
               transition it pretty silly in the first place */
            smooth_fade(pcm_transition, pcm,
                        pcm, F2_5,
                        st->channels, window, st->Fs);
        }
    }

    if(st->decode_gain)
    {
        opus_val32 gain;
        gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
        for (i=0; i<frame_size*st->channels; i++)
        {
            opus_val32 x;
            x = MULT16_32_P16(pcm[i],gain);
            pcm[i] = SATURATE(x, 32767);
        }
    }

    if (len <= 1)
        st->rangeFinal = 0;
    else
        st->rangeFinal = dec.rng ^ redundant_rng;

    st->prev_mode = mode;
    st->prev_redundancy = redundancy && !celt_to_silk;

    if (celt_ret>=0)
    {
        if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
            OPUS_PRINT_INT(audiosize);
    }

    RESTORE_STACK;
    return celt_ret < 0 ? celt_ret : audiosize;

}
示例#4
0
int opus_decoder_ctl(OpusDecoder *st, int request, ...)
{
   int ret = OPUS_OK;
   va_list ap;
   void *silk_dec;
   CELTDecoder *celt_dec;

   silk_dec = (char*)st+st->silk_dec_offset;
   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);


   va_start(ap, request);

   switch (request)
   {
   case OPUS_GET_BANDWIDTH_REQUEST:
   {
      opus_int32 *value = va_arg(ap, opus_int32*);
      *value = st->bandwidth;
   }
   break;
   case OPUS_GET_FINAL_RANGE_REQUEST:
   {
      opus_uint32 *value = va_arg(ap, opus_uint32*);
      *value = st->rangeFinal;
   }
   break;
   case OPUS_RESET_STATE:
   {
      OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
            sizeof(OpusDecoder)-
            ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));

      celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
      silk_InitDecoder( silk_dec );
      st->stream_channels = st->channels;
      st->frame_size = st->Fs/400;
   }
   break;
   case OPUS_GET_PITCH_REQUEST:
   {
      int *value = va_arg(ap, opus_int32*);
      if (value==NULL)
      {
         ret = OPUS_BAD_ARG;
         break;
      }
      if (st->prev_mode == MODE_CELT_ONLY)
         celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
      else
         *value = st->DecControl.prevPitchLag;
   }
   break;
   default:
      /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
      ret = OPUS_UNIMPLEMENTED;
      break;
   }

   va_end(ap);
   return ret;
}