/** * @brief Receive decoded audio frame. * * @param av Handler. * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes * and corresponds to one sample of audio.) * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels). * Make sure it has enough space for frame_size frames/samples. * @return int * @retval >=0 Size of received data in frames/samples. * @retval ToxAvError On error. */ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } CallSpecific *call = &av->calls[call_index]; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1); if ( dec_size < 0 ) { LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size)); return ErrorInternal; } else return dec_size; } else if ( recved_size ) { int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); if ( dec_size < 0 ) { LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size)); return ErrorInternal; } else return dec_size; } else { return 0; /* Nothing received */ } }
JNIEXPORT jbyteArray JNICALL Java_aopus_OpusLibrary_decoderDecode (JNIEnv *env, jobject obj, jlong state, jbyteArray encodedData) { Decoder *decoder = (Decoder *)state; // copy managed to unmanaged int encodedLength = (* env)->GetArrayLength(env, encodedData); unsigned char *encodedDataBytes = malloc(encodedLength); (* env)->GetByteArrayRegion(env, encodedData, 0, encodedLength, encodedDataBytes); int numSamplesDecoded; int bandwidth = opus_packet_get_bandwidth(encodedDataBytes); if (bandwidth == OPUS_INVALID_PACKET) { numSamplesDecoded = opus_decode(decoder->dec, 0, 0, (opus_int16 *)decoder->buffer, decoder->frameSizePerChannel, 0); decoder->previousPacketInvalid = 1; } else { numSamplesDecoded = opus_decode(decoder->dec, encodedDataBytes, encodedLength, (opus_int16 *)decoder->buffer, decoder->frameSizePerChannel, decoder->previousPacketInvalid); decoder->previousPacketInvalid = 0; } free(encodedDataBytes); if (numSamplesDecoded > 0) { // copy unmanaged to managed int frameLength = numSamplesDecoded * decoder->channels * 2; jbyteArray frame = (* env)->NewByteArray(env, frameLength); // 2 bytes per sample (* env)->SetByteArrayRegion(env, frame, 0, frameLength, decoder->buffer); return frame; } return NULL; }
/** * @brief Receive decoded audio frame. * * @param av Handler. * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes * and corresponds to one sample of audio.) * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels). * Make sure it has enough space for frame_size frames/samples. * @return int * @retval >=0 Size of received data in frames/samples. * @retval ToxAvError On error. */ inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); } else if ( recved_size ) { return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); } else { return 0; /* Nothing received */ } }
CODEC_API int PLG_DECODE_V1(opus_48000)(void* opaqueCodecContext, const void* encodedData, unsigned encodedPacketSize, void* pcmAudioBuffer, unsigned pcmBufferSize, unsigned* decodedSamples, const struct RtpHeader* rtpHeader) { int status = RPLG_INVALID_ARGUMENT; assert(opaqueCodecContext); struct MpCodecOpusCodecState* decoderContext = (struct MpCodecOpusCodecState*) opaqueCodecContext; assert(decoderContext->mCodecType == CODEC_DECODE); assert(decoderContext->mpDecoderContext); int useFec = 1; /* 1=true, 0=false */ int numSamples = opus_decode(decoderContext->mpDecoderContext, encodedData, encodedPacketSize, pcmAudioBuffer, pcmBufferSize, useFec); if(numSamples < 0) { *decodedSamples = 0; status = OpusToPluginError(numSamples); mppLogError("opus_decode(decoderContext: %p, packet: %p, packetSize: %d, audioBuf: %p, bufSize: %d, useFec: %d)", decoderContext->mpDecoderContext, encodedData, encodedPacketSize, pcmAudioBuffer, pcmBufferSize, useFec); } // Successful decode else { *decodedSamples = numSamples; status = RPLG_SUCCESS; } return(status); }
virtual bool Transcode(const void * fromPtr, unsigned & fromLen, void * toPtr, unsigned & toLen, unsigned & flags) { int samples = opus_decoder_get_nb_samples(m_decoder, (const unsigned char *)fromPtr, fromLen); if (samples < 0) { PTRACE(1, MY_CODEC_LOG, "Decoding error " << samples << ' ' << opus_strerror(samples)); return false; } if (samples*m_channels*2 > (int)toLen) { PTRACE(1, MY_CODEC_LOG, "Provided sample buffer too small, " << toLen << " bytes"); return false; } int result = opus_decode(m_decoder, (const unsigned char *)fromPtr, fromLen, (opus_int16 *)toPtr, samples, 0); if (result < 0) { PTRACE(1, MY_CODEC_LOG, "Decoder error " << result << ' ' << opus_strerror(result)); return false; } toLen = result*m_channels*2; return true; }
AM_UINT CAudioCodecOpus::decode(AM_U8 *input, AM_UINT inDataSize, AM_U8 *output, AM_UINT *outDataSize) { int totalFrames = opus_packet_get_nb_frames(input, inDataSize); int totalSamples = (totalFrames > 0) ? totalFrames * opus_packet_get_samples_per_frame(input, 48000) : -1; AM_UINT ret = (AM_UINT)-1; if (AM_LIKELY((totalSamples >= 120) && (totalSamples <= 120*48))) { *outDataSize = 0; while (totalSamples > 0) { int decodedSample = opus_decode(mDecoder, (const unsigned char*)input, (opus_int32)inDataSize, (((opus_int16*)output) + *outDataSize), 120*48, 0); if (AM_LIKELY(decodedSample > 0)) { totalSamples -= decodedSample; *outDataSize += decodedSample * sizeof(AM_U16) * 2; } else { ret = (AM_UINT)-1; break; } } if (AM_LIKELY(totalSamples == 0)) { ret = inDataSize; } } return ret; }
/* src=NULL means lost packet */ static int decode(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src) { int r; if (!mbuf_get_left(src) && !st->got_packet) return 0; /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { int err = mbuf_resize(dst, dst->pos + st->fsize); if (err) return err; } r = opus_decode(st->dec, mbuf_buf(src), (int)mbuf_get_left(src), (short *)mbuf_buf(dst), st->frame_size, 0); if (r <= 0) { DEBUG_WARNING("opus_decode: r=%d (%u bytes)\n", r, mbuf_get_left(src)); return EBADMSG; } if (src) src->pos = src->end; dst->end += 2 * r * aucodec_ch(st->ac); st->got_packet = true; return 0; }
virtual bool Transcode(const void * fromPtr, unsigned & fromLen, void * toPtr, unsigned & toLen, unsigned & flags) { int samples; const unsigned char * packet; if (fromLen == 0) { packet = NULL; // As per opus_decode() API opus_decoder_ctl(m_decoder, OPUS_GET_LAST_PACKET_DURATION(&samples)); } else { packet = (const unsigned char *)fromPtr; samples = opus_decoder_get_nb_samples(m_decoder, packet, fromLen); if (samples < 0) { PTRACE(1, MY_CODEC_LOG, "Decoding error " << samples << ' ' << opus_strerror(samples)); return false; } } if ((unsigned)samples*m_channels*2U > toLen) { PTRACE(1, MY_CODEC_LOG, "Provided sample buffer too small, " << toLen << " bytes"); return false; } int result = opus_decode(m_decoder, packet, fromLen, (opus_int16 *)toPtr, samples, m_useInBandFEC); if (result < 0) { PTRACE(1, MY_CODEC_LOG, "Decoder error " << result << ' ' << opus_strerror(result)); return false; } toLen = result*m_channels*2; return true; }
static int opus_plc( unsigned char* out_buf, unsigned int size, unsigned int channels, unsigned int rate, long h_codec ) { opus_state_t* codec_inst; int res; if (!h_codec){ ERROR("opus codec not initialized.\n"); return 0; } codec_inst = (opus_state_t*)h_codec; if (size/channels > AUDIO_BUFFER_SIZE) { /* DBG("OPUS plc: size %d, chan %d exceeds buffer size %d.\n", size, channels, AUDIO_BUFFER_SIZE); */ return 0; } if (0<(res = opus_decode(codec_inst->opus_dec, NULL, 0, (opus_int16*)out_buf, size/2/channels, 0))) { /* returns samples in encoded frame */ res*=2; } /* DBG ("OPUS plc: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res); */ return res; }
/* * Recover lost frame. */ static pj_status_t opus_codec_recover(pjmedia_codec *codec, unsigned output_buf_len, struct pjmedia_frame *output) { struct opus_private *opus; int ret = 0; int frame_size; PJ_ASSERT_RETURN(output, PJ_EINVAL); opus = (struct opus_private *)codec->codec_data; frame_size = output_buf_len / opus->pcm_bytes_per_sample; /* Decode */ ret = opus_decode(opus->psDec, (const unsigned char *)NULL, 0, output->buf, frame_size, 0); if (ret < 0) { PJ_LOG(1, (THIS_FILE, "Failed to recover opus frame %d", ret)); return PJ_EINVAL; } else if (ret == 0) { #if _TRACE_OPUS PJ_LOG(4, (THIS_FILE, "Empty frame recovered %d", ret)); #endif output->type = PJMEDIA_FRAME_TYPE_NONE; output->buf = NULL; output->size = 0; } else { #if _TRACE_OPUS PJ_LOG(4, (THIS_FILE, "Frame recovered %d", ret)); #endif output->size = ret * opus->pcm_bytes_per_sample; output->type = PJMEDIA_FRAME_TYPE_AUDIO; } return PJ_SUCCESS; }
JNIEXPORT jint JNICALL Java_com_score_rahasak_utils_OpusDecoder_nativeDecodeBytes (JNIEnv *env, jobject obj, jbyteArray in, jshortArray out) { jint inputArraySize = (*env)->GetArrayLength(env, in); jint outputArraySize = (*env)->GetArrayLength(env, out); jbyte* encodedData = (*env)->GetByteArrayElements(env, in, 0); opus_int16 *data = (opus_int16*)calloc(outputArraySize,sizeof(opus_int16)); int decodedDataArraySize = opus_decode(dec, encodedData, inputArraySize, data, FRAME_SIZE, 0); if (decodedDataArraySize >=0) { if (decodedDataArraySize <= outputArraySize) { (*env)->SetShortArrayRegion(env,out,0,decodedDataArraySize,data); } else { sprintf(logMsg, "Output array of size: %d to small for storing encoded data.", outputArraySize); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); return -1; } } (*env)->ReleaseByteArrayElements(env,in,encodedData,JNI_ABORT); return decodedDataArraySize; }
static int opustolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) { struct opus_coder_pvt *opvt = pvt->pvt; int samples = 0; /* Decode */ ast_debug(3, "[Decoder #%d (%d)] %d samples, %d bytes\n", opvt->id, opvt->sampling_rate, f->samples, f->datalen); if ((samples = opus_decode(opvt->opus, f->data.ptr, f->datalen, pvt->outbuf.i16, BUFFER_SAMPLES, opvt->fec)) < 0) { ast_log(LOG_ERROR, "Error decoding the Opus frame: %s\n", opus_strerror(samples)); return -1; } pvt->samples += samples; pvt->datalen += samples * 2; ast_debug(3, "[Decoder #%d (%d)] >> Got %d samples, %d bytes\n", opvt->id, opvt->sampling_rate, pvt->samples, pvt->datalen); return 0; }
void SoundOpusData::onRender() { if(_samples && samplesDecodingProgress != _frames) { Decoder* dec = 0; foreach(e, decoders) { if(e->first == 0) { dec = e; break; } } if(!dec) { dec = decoders.push(); int err; dec->decoder = opus_decoder_create(AUDIOLIB_FRAME_RATE, _channels, &err); dec->first = 0; dec->end = 0; } if(dec->end == samplesDecodingProgress) { uint packet = dec->end / SOUNDLIB_OPUS_PACKET_FRAMES; opus_decode(dec->decoder, _opusData + SOUNDLIB_OPUS_PACKET_SIZE * _channels * packet, SOUNDLIB_OPUS_PACKET_SIZE * _channels, _samples + _channels * packet * SOUNDLIB_OPUS_PACKET_FRAMES, SOUNDLIB_OPUS_PACKET_FRAMES, 0); dec->end += SOUNDLIB_OPUS_PACKET_FRAMES; dec->unusedCount = 0; } samplesDecodingProgress = dec->end; }
static switch_status_t switch_opus_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) { struct opus_context *context = codec->private_info; int samples = 0; uint32_t frame_size; uint32_t frame_samples; if (!context) { return SWITCH_STATUS_FALSE; } frame_samples = *decoded_data_len / 2 / codec->implementation->number_of_channels; frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400)); samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, frame_size, !!(*flag & SFF_PLC)); if (samples < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error: %s fs:%u plc:%d!\n", opus_strerror(samples), frame_size, !!(*flag & SFF_PLC)); return SWITCH_STATUS_GENERR; } *decoded_data_len = samples * 2 * codec->implementation->number_of_channels; return SWITCH_STATUS_SUCCESS; }
/* * Recover lost frame. */ static pj_status_t codec_recover( pjmedia_codec *codec, unsigned output_buf_len, struct pjmedia_frame *output ) { struct opus_data *opus_data = (struct opus_data *)codec->codec_data; int decoded_samples; pjmedia_frame *inframe; pj_mutex_lock (opus_data->mutex); if (opus_data->dec_frame_index == -1) { /* Recover the first packet? Don't think so, fill it with zeroes. */ pj_uint16_t samples_per_frame; samples_per_frame = (opus_data->cfg.sample_rate * opus_data->ptime) / 1000; output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->size = samples_per_frame << 1; pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame); pj_mutex_unlock (opus_data->mutex); return PJ_SUCCESS; } inframe = &opus_data->dec_frame[opus_data->dec_frame_index]; decoded_samples = opus_decode(opus_data->dec, inframe->type==PJMEDIA_FRAME_TYPE_AUDIO ? inframe->buf : NULL, inframe->type==PJMEDIA_FRAME_TYPE_AUDIO ? inframe->size : 0, (opus_int16*)output->buf, output->size / (sizeof(opus_int16) * opus_data->cfg.channel_cnt), 0); /* Mark current indexed frame as invalid */ inframe->type = PJMEDIA_FRAME_TYPE_NONE; /* Update current frame index */ opus_data->dec_frame_index++; if (opus_data->dec_frame_index > 1) opus_data->dec_frame_index = 0; /* Mark current indexed frame as invalid */ inframe = &opus_data->dec_frame[opus_data->dec_frame_index]; inframe->type = PJMEDIA_FRAME_TYPE_NONE; if (decoded_samples < 0) { PJ_LOG(4, (THIS_FILE, "Recover failed!")); pj_mutex_unlock (opus_data->mutex); return PJMEDIA_CODEC_EFAILED; } output->size = decoded_samples * sizeof(opus_int16) * opus_data->cfg.channel_cnt; output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->timestamp = inframe->timestamp; pj_mutex_unlock (opus_data->mutex); return PJ_SUCCESS; }
static tsk_size_t tdav_codec_opus_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr) { tdav_codec_opus_t* opus = (tdav_codec_opus_t*)self; int frame_size; const trtp_rtp_header_t* rtp_hdr = proto_hdr; if(!self || !in_data || !in_size || !out_data) { TSK_DEBUG_ERROR("Invalid parameter"); return 0; } if(!opus->decoder.inst) { TSK_DEBUG_ERROR("Decoder not ready"); return 0; } /* Packet loss? */ if(opus->decoder.last_seq != (rtp_hdr->seq_num - 1) && opus->decoder.last_seq) { if(opus->decoder.last_seq == rtp_hdr->seq_num) { // Could happen on some stupid emulators //TSK_DEBUG_INFO("Packet duplicated, seq_num=%d", rtp_hdr->seq_num); return 0; } TSK_DEBUG_INFO("[Opus] Packet loss, seq_num=%d", rtp_hdr->seq_num); opus_decode(opus->decoder.inst, tsk_null/*packet loss*/, (opus_int32)0, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled); } opus->decoder.last_seq = rtp_hdr->seq_num; frame_size = opus_decode(opus->decoder.inst, (const unsigned char *)in_data, (opus_int32)in_size, opus->decoder.buff, TDAV_OPUS_MAX_FRAME_SIZE_IN_SAMPLES, opus->decoder.fec_enabled ? 1 : 0); if(frame_size > 0) { tsk_size_t frame_size_inbytes = (frame_size << 1); if(*out_max_size < frame_size_inbytes) { if(!(*out_data = tsk_realloc(*out_data, frame_size_inbytes))) { TSK_DEBUG_ERROR("Failed to allocate new buffer"); *out_max_size = 0; return 0; } *out_max_size = frame_size_inbytes; } memcpy(*out_data, opus->decoder.buff, frame_size_inbytes); return frame_size_inbytes; } else { return 0; } }
static void sdl_renderer_decode_and_play_sample(char* data, int length) { int decodeLen = opus_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); if (decodeLen > 0) { SDL_QueueAudio(dev, pcmBuffer, decodeLen * CHANNEL_COUNT * sizeof(short)); } else { printf("Opus error from decode: %d\n", decodeLen); } }
int Opus::decode(std::vector<std::vector<SFLAudioSample> > &pcm) { if (!lastDecodedFrameSize_) return 0; int ret; if (channelsCur_ == 1) { ret = opus_decode(decoder_, nullptr, 0, pcm[0].data(), lastDecodedFrameSize_, 0); } else { std::array<SFLAudioSample, 2 * MAX_PACKET_SIZE> ibuf; // deinterleave on stack, 11.25KiB used. ret = opus_decode(decoder_, nullptr, 0, ibuf.data(), lastDecodedFrameSize_, 0); for (int i = 0; i < ret; i++) { pcm[0][i] = ibuf[2 * i]; pcm[1][i] = ibuf[2 * i + 1]; } } if (ret < 0) std::cerr << opus_strerror(ret) << std::endl; return ret; }
// outpcmdata must be 5760*2 shorts in length // packets must be decoded in order // a packet loss must call this function with NULL indata and 0 inlen // returns the number of decoded samples int nv_opus_decode(unsigned char* indata, int inlen, short* outpcmdata) { int err; // Decoding to 16-bit PCM with FEC off // Maximum length assuming 48KHz sample rate err = opus_decode(decoder, indata, inlen, outpcmdata, 512, 0); return err; }
JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decode (JNIEnv *env, jclass clazz, jlong decoder, jbyteArray input, jint inputOffset, jint inputLength, jbyteArray output, jint outputOffset, jint outputFrameSize, jint decodeFEC) { int ret; if (output) { jbyte *input_; if (input && inputLength) { input_ = (*env)->GetPrimitiveArrayCritical(env, input, 0); ret = input_ ? OPUS_OK : OPUS_ALLOC_FAIL; } else { input_ = 0; ret = OPUS_OK; } if (OPUS_OK == ret) { jbyte *output_ = (*env)->GetPrimitiveArrayCritical(env, output, 0); if (output_) { ret = opus_decode( (OpusDecoder *) (intptr_t) decoder, (unsigned char *) (input_ ? (input_ + inputOffset) : NULL), inputLength, (opus_int16 *) (output_ + outputOffset), outputFrameSize, decodeFEC); (*env)->ReleasePrimitiveArrayCritical(env, output, output_, 0); } else ret = OPUS_ALLOC_FAIL; if (input_) { (*env)->ReleasePrimitiveArrayCritical( env, input, input_, JNI_ABORT); } } } else ret = OPUS_BAD_ARG; return ret; }
EMSCRIPTEN_KEEPALIVE int decode(Encoder* encoder, int length) { int encoded_frames = opus_decode( encoder->decoder, encoder->in_opus,//opus, length, encoder->in_decoded, MAX_FRAME_SIZE, 0 ); to_little_endian(encoder->in_decoded, MAX_OUTPUT_BYTES, encoder->out_little_endian); return encoded_frames; }
static void audio_renderer_decode_and_play_sample(char* data, int length) { int decodeLen = opus_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); if (decodeLen > 0) { int rc = snd_pcm_writei(handle, pcmBuffer, decodeLen); if (rc == -EPIPE) snd_pcm_recover(handle, rc, 1); if (rc<0) printf("Alsa error from writei: %d\n", rc); else if (decodeLen != rc) printf("Alsa shortm write, write %d frames\n", rc); } else { printf("Opus error from decode: %d\n", decodeLen); } }
static int DecodeNative(OpusDecoder* inst, int16_t* encoded, int16_t encoded_bytes, int16_t* decoded, int16_t* audio_type) { unsigned char* coded = (unsigned char*) encoded; opus_int16* audio = (opus_int16*) decoded; int res = opus_decode(inst, coded, encoded_bytes, audio, kWebRtcOpusMaxFrameSize, 0); /* TODO(tlegrand): set to DTX for zero-length packets? */ *audio_type = 0; if (res > 0) { return res; } return -1; }
int16_t WebRtcOpus_DecodeNative(OpusDecInst *inst, int16_t *encoded, int16_t len, int16_t *decoded, int16_t *audioType) { unsigned char *coded = (unsigned char *)encoded; opus_int16 *audio = (opus_int16 *)decoded; int res = opus_decode(inst->decoder, coded, len, audio, WEBRTC_OPUS_MAX_FRAME_SIZE, 0); /* TODO: set to DTX for zero-length packets? */ *audioType = 0; if(res > 0) { return res; } return -1; }
/* * Class: de_stuttgart_hdm_opuswalkietalkie_OpusDecoder * Method: nativeDecodeBytes * Signature: ([B;[S)I */ JNIEXPORT jint JNICALL Java_de_stuttgart_hdm_opuswalkietalkie_OpusDecoder_nativeDecodeBytes (JNIEnv *env, jobject obj, jbyteArray in, jshortArray out) { __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", "Opus decoding"); sprintf(logMsg, "FrameSize: %d - SamplingRate: %d - Channels: %d", FRAME_SIZE, SAMPLING_RATE, CHANNELS); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); jint inputArraySize = (*env)->GetArrayLength(env, in); jint outputArraySize = (*env)->GetArrayLength(env, out); sprintf(logMsg, "Length of Input Array: %d", inputArraySize); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); sprintf(logMsg, "Length of Output Array: %d", outputArraySize); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); jbyte* encodedData = (*env)->GetByteArrayElements(env, in, 0); opus_int16 *data = (opus_int16*)calloc(outputArraySize,sizeof(opus_int16)); int decodedDataArraySize = opus_decode(dec, encodedData, inputArraySize, data, FRAME_SIZE, 0); sprintf(logMsg, "Length of Decoded Data: %d", decodedDataArraySize); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); if (decodedDataArraySize >=0) { if (decodedDataArraySize <= outputArraySize) { (*env)->SetShortArrayRegion(env,out,0,decodedDataArraySize,data); } else { sprintf(logMsg, "Output array of size: %d to small for storing encoded data.", outputArraySize); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); return -1; } } (*env)->ReleaseByteArrayElements(env,in,encodedData,JNI_ABORT); return decodedDataArraySize; }
int tc_opus_decode(OpusDecoder *decoder, unsigned char *cbits, int nbBytes, unsigned char *pcm_bytes, int channels, int max_frame_size) { int err=0, i; opus_int16 out[max_frame_size*channels]; int frame_size = opus_decode(decoder, cbits, nbBytes, out, max_frame_size, 0); if (frame_size<0) { pa_log_error("decoder failed: %s", opus_strerror(err)); return EXIT_FAILURE; } /* Convert to little-endian ordering. */ for(i=0;i<channels*frame_size;i++) { pcm_bytes[2*i]=out[i]&0xFF; pcm_bytes[2*i+1]=(out[i]>>8)&0xFF; } return frame_size; }
static int opus_2_pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, unsigned int channels, unsigned int rate, long h_codec ) { opus_state_t* codec_inst; int res; if (!h_codec){ ERROR("opus codec not initialized.\n"); return 0; } codec_inst = (opus_state_t*)h_codec; if (0<(res = opus_decode(codec_inst->opus_dec, in_buf, size, (opus_int16*)out_buf, AUDIO_BUFFER_SIZE/2, 0))) { /* returns samples in encoded frame */ res*=2; } /* DBG ("OPUS decode: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res); */ return res; }
QByteArray OpusDecode::decode(const QByteArray &data) { if (!initialized) return QByteArray(); int i; int frame_size; /* Decode the data. In this example, frame_size will be constant because the encoder is using a constant frame size. However, that may not be the case for all encoders, so the decoder must always check the frame size returned. */ opus_int16 *out = new opus_int16[FRAME_SIZE*channels]; frame_size = opus_decode(decoder, (unsigned char*)data.data(), data.size(), out, MAX_FRAME_SIZE, 0); if (frame_size<0) { qDebug() << "decoder failed:" << opus_strerror(frame_size); delete[] out; return QByteArray(); } int size = sizeof(qint16)*channels*frame_size; unsigned char *pcm_bytes = new unsigned char[size]; /* Convert to little-endian ordering. */ for(i=0;i<channels*frame_size;i++) { pcm_bytes[2*i]=out[i]&0xFF; pcm_bytes[2*i+1]=(out[i]>>8)&0xFF; } /* Write the decoded audio to file. */ QByteArray output((char*)pcm_bytes, size); delete[] pcm_bytes; delete[] out; return output; }
static void decode_audio(ToxAv *av, CallSpecific *call, DECODE_PACKET *p) { int32_t call_index = call - av->calls; // ToxAvCSettings csettings; // toxav_get_peer_csettings(av, call_index, 0, &csettings); int frame_size = 10000; /* FIXME: not static? */ int16_t dest[frame_size]; int dec_size = opus_decode(call->cs->audio_decoder, p->data, p->size, dest, frame_size, (p->size == 0)); free(p); if (dec_size < 0) { LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size)); return; } if ( av->audio_callback ) av->audio_callback(av, call_index, dest, dec_size, av->audio_callback_userdata); else LOGGER_WARNING("Audio packet dropped due to missing callback!"); }
static switch_status_t switch_opus_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) { struct opus_context *context = codec->private_info; int samples = 0; if (!context) { return SWITCH_STATUS_FALSE; } samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, *decoded_data_len, 0); if (samples < 0) { return SWITCH_STATUS_GENERR; } *decoded_data_len = samples * 2; return SWITCH_STATUS_SUCCESS; }