internal static OpusBandwidth MAX(OpusBandwidth a, OpusBandwidth b) { if ((int)a > (int)b) { return(a); } return(b); }
/// <summary> /// OPUS_DECODER_RESET_START /// </summary> internal void PartialReset() { stream_channels = 0; bandwidth = 0; mode = 0; prev_mode = 0; frame_size = 0; prev_redundancy = 0; last_packet_duration = 0; rangeFinal = 0; // fixme: do these get reset here? I don't think they do because init_celt and init_silk should both call RESET_STATE on their respective states //SilkDecoder.Reset(); //CeltDecoder.Reset(); }
internal static byte gen_toc(OpusMode mode, int framerate, OpusBandwidth bandwidth, int channels) { int period; byte toc; period = 0; while (framerate < 400) { framerate <<= 1; period++; } if (mode == OpusMode.MODE_SILK_ONLY) { toc = (byte)((bandwidth - OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) << 5); toc |= (byte)((period - 2) << 3); } else if (mode == OpusMode.MODE_CELT_ONLY) { int tmp = bandwidth - OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND; if (tmp < 0) { tmp = 0; } toc = 0x80; toc |= (byte)(tmp << 5); toc |= (byte)(period << 3); } else /* Hybrid */ { toc = 0x60; toc |= (byte)((bandwidth - OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) << 4); toc |= (byte)((period - 2) << 3); } toc |= (byte)((channels == 2 ? 1 : 0) << 2); return(toc); }
internal int opus_decode_native(byte[] data, int data_ptr, int len, short[] pcm_out, int pcm_out_ptr, int frame_size, int decode_fec, int self_delimited, out int packet_offset, int soft_clip) { int i, nb_samples; int count, offset; byte toc; int packet_frame_size, packet_stream_channels; packet_offset = 0; OpusBandwidth packet_bandwidth; OpusMode packet_mode; /* 48 x 2.5 ms = 120 ms */ // fixme: make sure these values can fit in an int16 short[] size = new short[48]; if (decode_fec < 0 || decode_fec > 1) { return(OpusError.OPUS_BAD_ARG); } /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec != 0 || len == 0 || data == null) && frame_size % (this.Fs / 400) != 0) { return(OpusError.OPUS_BAD_ARG); } if (len == 0 || data == null) { int pcm_count = 0; do { int ret; ret = opus_decode_frame(null, 0, 0, pcm_out, pcm_out_ptr + (pcm_count * this.channels), frame_size - pcm_count, 0); if (ret < 0) { return(ret); } pcm_count += ret; } while (pcm_count < frame_size); Inlines.OpusAssert(pcm_count == frame_size); this.last_packet_duration = pcm_count; return(pcm_count); } else if (len < 0) { return(OpusError.OPUS_BAD_ARG); } packet_mode = OpusPacketInfo.GetEncoderMode(data, data_ptr); packet_bandwidth = OpusPacketInfo.GetBandwidth(data, data_ptr); packet_frame_size = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, this.Fs); packet_stream_channels = OpusPacketInfo.GetNumEncodedChannels(data, data_ptr); count = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out toc, null, null, 0, size, 0, out offset, out packet_offset); if (count < 0) { return(count); } data_ptr += offset; if (decode_fec != 0) { int dummy; int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size < packet_frame_size || packet_mode == OpusMode.MODE_CELT_ONLY || this.mode == OpusMode.MODE_CELT_ONLY) { return(opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size, 0, 0, out dummy, soft_clip)); } /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = this.last_packet_duration; if (frame_size - packet_frame_size != 0) { ret = opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size - packet_frame_size, 0, 0, out dummy, soft_clip); if (ret < 0) { this.last_packet_duration = duration_copy; return(ret); } Inlines.OpusAssert(ret == frame_size - packet_frame_size); } /* Complete with FEC */ this.mode = packet_mode; this.bandwidth = packet_bandwidth; this.frame_size = packet_frame_size; this.stream_channels = packet_stream_channels; ret = opus_decode_frame(data, data_ptr, size[0], pcm_out, pcm_out_ptr + (this.channels * (frame_size - packet_frame_size)), packet_frame_size, 1); if (ret < 0) { return(ret); } else { this.last_packet_duration = frame_size; return(frame_size); } } if (count * packet_frame_size > frame_size) { return(OpusError.OPUS_BUFFER_TOO_SMALL); } /* Update the state as the last step to avoid updating it on an invalid packet */ this.mode = packet_mode; this.bandwidth = packet_bandwidth; this.frame_size = packet_frame_size; this.stream_channels = packet_stream_channels; nb_samples = 0; for (i = 0; i < count; i++) { int ret; ret = opus_decode_frame(data, data_ptr, size[i], pcm_out, pcm_out_ptr + (nb_samples * this.channels), frame_size - nb_samples, 0); if (ret < 0) { return(ret); } Inlines.OpusAssert(ret == packet_frame_size); data_ptr += size[i]; nb_samples += ret; } this.last_packet_duration = nb_samples; return(nb_samples); }
internal static int GetOrdinal(OpusBandwidth bw) { return((int)bw - (int)OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND); }
public AudioChunk Decompress(byte[] inputPacket) { int frameSize = GetFrameSize(); short[] outputBuffer = new short[frameSize]; bool lostPacket = new Random().Next(0, 100) < _packetLoss; if (!lostPacket) { // Normal decoding _timer.Reset(); _timer.Start(); int thisFrameSize = _decoder.Decode(inputPacket, 0, inputPacket.Length, outputBuffer, 0, frameSize, false); _timer.Stop(); } else { // packet loss path _timer.Reset(); _timer.Start(); int thisFrameSize = _decoder.Decode(null, 0, 0, outputBuffer, 0, frameSize, true); _timer.Stop(); } short[] finalOutput = new short[frameSize]; Array.Copy(outputBuffer, finalOutput, finalOutput.Length); // Update statistics _statistics.Bitrate = inputPacket.Length * 8 * 48000 / 1024 / frameSize; OpusMode curMode = OpusPacketInfo.GetEncoderMode(inputPacket, 0); if (curMode == OpusMode.MODE_CELT_ONLY) { _statistics.Mode = "CELT"; } else if (curMode == OpusMode.MODE_HYBRID) { _statistics.Mode = "Hybrid"; } else if (curMode == OpusMode.MODE_SILK_ONLY) { _statistics.Mode = "SILK"; } else { _statistics.Mode = "Unknown"; } _statistics.DecodeSpeed = _frameSize / ((double)_timer.ElapsedTicks / Stopwatch.Frequency * 1000); OpusBandwidth curBandwidth = OpusPacketInfo.GetBandwidth(inputPacket, 0); if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) { _statistics.Bandwidth = 8000; } else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND) { _statistics.Bandwidth = 12000; } else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND) { _statistics.Bandwidth = 16000; } else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) { _statistics.Bandwidth = 24000; } else { _statistics.Bandwidth = 48000; } return new AudioChunk(finalOutput, 48000); }