/// <summary> /// Initializes a new instance of the <see cref="OpusSource"/> class. /// </summary> /// <param name="stream">The stream.</param> /// <param name="sampleRate">The sample rate.</param> /// <param name="channels">The channels.</param> public OpusSource(Stream stream, int sampleRate, int channels) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead) { throw new ArgumentException("Stream is not readable.", nameof(stream)); } _stream = stream; WaveFormat = new WaveFormat(sampleRate, BitsPerSample, channels); var decoder = new OpusDecoder(WaveFormat.SampleRate, WaveFormat.Channels); _opusReadStream = new OpusOggReadStream(decoder, stream); _cts.Token.Register(() => { decoder.ResetState(); }); }
/// <summary> /// Seeks the stream for a valid packet at the specified granule position. /// </summary> /// <param name="granulePosition">The granule position.</param> private void SeekToGranulePosition(long granulePosition) { if (!CanSeek) { throw new InvalidOperationException("Stream is not seekable."); } if (granulePosition < 0 || granulePosition > GranuleCount) { throw new ArgumentOutOfRangeException(nameof(granulePosition)); } // Find a packet based on offset and return 1 in the callback if the packet is valid var foundPacket = _packetProvider.FindPacket(granulePosition, GetPacketLength); // Check of the found packet is valid if (foundPacket == null || foundPacket.IsEndOfStream) { _endOfStream = true; _nextDataPacket = null; return; } // Just seek to this found packet and get the previous packet (preRoll = 1) _packetProvider.SeekToPacket(foundPacket, 1); // Update the PageGranulePosition to the position from this next packet which will be retrieved by the next QueueNextPacket call PageGranulePosition = _packetProvider.PeekNextPacket().PageGranulePosition; // Reset the state from the decoder to start processing a fresh stream _decoder.ResetState(); }
public void togglePlayingTCP() { if (sdsock != null) { sdsock.Dispose(); sdsock = null; if (concentusOpusDecoder != null) { concentusOpusDecoder.ResetState(); concentusOpusDecoder = null; } m_Player.Close(); } else { sdsock = new SoundDataSocket(NetworkTypes.Client); sdsock.ConnectedCallback += Socket_ConnectedCallback; sdsock.DisconnectedCallback += Socket_DisconnectedCallback; sdsock.ConnectionFailedCallback += Socket_ConnectionFailedCallback; sdsock.DataRecievedCallback += Socket_DataRecievedCallback; sdsock.StartDataRecievedCallback += Socket_StartDataRecievedCallback; sdsock.EndDataRecievedCallback += Socket_EndDataRecievedCallback; sdsock.Connect(System.Net.IPAddress.Parse(GlobalConfiguration.ServerAddress), config.SoundServerPort); } }
private ResultCode DecodeInterleavedInternal(BinaryReader input, out short[] outPcmData, long outputSize, out uint outConsumed, out int outSamples) { outPcmData = null; outConsumed = 0; outSamples = 0; long streamSize = input.BaseStream.Length; if (streamSize < Marshal.SizeOf <OpusPacketHeader>()) { return(ResultCode.OpusInvalidInput); } OpusPacketHeader header = OpusPacketHeader.FromStream(input); uint totalSize = header.length + (uint)Marshal.SizeOf <OpusPacketHeader>(); if (totalSize > streamSize) { return(ResultCode.OpusInvalidInput); } byte[] opusData = input.ReadBytes((int)header.length); ResultCode result = GetPacketNumSamples(out int numSamples, opusData); if (result == ResultCode.Success) { if ((uint)numSamples * (uint)_channelsCount * sizeof(short) > outputSize) { return(ResultCode.OpusInvalidInput); } outPcmData = new short[numSamples * _channelsCount]; if (_reset) { _reset = false; _decoder.ResetState(); } try { outSamples = _decoder.Decode(opusData, 0, opusData.Length, outPcmData, 0, outPcmData.Length / _channelsCount); outConsumed = totalSize; } catch (OpusException) { // TODO: as OpusException doesn't provide us the exact error code, this is kind of inaccurate in some cases... return(ResultCode.OpusInvalidInput); } } return(ResultCode.Success); }
public async Task Stop() { if (playing) { playing = false; BasePlayer.Stop(); if (provideThread != null) { provideThread.Abort(); await Task.Run(() => provideThread.Join()); provideThread = null; } decoder.ResetState(); } }
public Sound LoadSound(string filepath) { //Read ogg packets FileStream stream = new FileStream(filepath, FileMode.Open); byte[][] packets = GetAudioPackets(stream); List <byte> pcmBytes = new List <byte>(); //Decode packets from opus to pcm for (int i = 0; i < packets.Length; i++) { try { var packet = packets[i]; int frameSize = OpusPacketInfo.GetNumSamplesPerFrame(packet, 0, SAMPLE_RATE); //Get frame size from opus packet short[] rawBuffer = new short[frameSize * 2]; //2 channels var buffer = decoder.Decode(packet, 0, packet.Length, rawBuffer, 0, frameSize, false); //Convert shorts to bytes byte[] result = new byte[rawBuffer.Length * 2]; for (int j = 0; j < rawBuffer.Length; j++) { byte[] val = BitConverter.GetBytes(rawBuffer[j]); Array.Copy(val, 0, result, j * 2, 2); } pcmBytes.AddRange(result); } catch (Concentus.OpusException e) { //Skip this frame //Note: the first 2 frames will hit this exception (they're probably just metadata frames, but i'm too lazy to check) } } decoder.ResetState(); return(Sound.FromS16LE(pcmBytes.ToArray())); }
public async Task Stop(bool isSoft) { if (playing) { playing = false; if (!isSoft) { BasePlayer.Playing = false; } if (provideThread != null) { BaseStream.Dispose(); provideThread.Abort(); await Task.Run(() => provideThread.Join()); provideThread = null; } decoder.ResetState(); } }
public void ResetState() { _decoder.ResetState(); }