/// <summary> /// Accepts Base64 data encoded as a char array and writes it to the binary stream. /// </summary> /// <param name="buffer">Array of char representing the base64 data</param> /// <param name="offset">Zero based element position to start encoding</param> /// <param name="count">The Number of chars to decode</param> /// <returns>The number of bytes consumed by the conversion (which may not be the whole array)</returns> public async Task <int> Write(char[] buffer, int offset, int count) { // must write in multiples of 4. We need to add any unwritten buffer to the front var charsToWrite = 4 * ((int)((count + unwritten.Length) / 4)); var newChars = new char[charsToWrite]; var newDataStartPoint = unwritten.Length; var newCount = charsToWrite - unwritten.Length; if (unwritten.Length > 0) { Array.Copy(unwritten.ToCharArray(), 0, newChars, 0, unwritten.Length); } ; Array.Copy(buffer, 0, newChars, newDataStartPoint, newCount); var newBytes = Convert.FromBase64CharArray(newChars, 0, charsToWrite); //keep the unwritten part for next time. var unwrittenSize = (count - newCount); if (unwrittenSize > 0) { unwritten = new string(buffer, count - unwrittenSize, unwrittenSize); } if (!Ignore) { await OutStream.WriteAsync(newBytes, 0, newBytes.Length); } return(charsToWrite); }
public Task WriteAsync(int value, CancellationToken cancellationToken) { byte[] buffer = Buffer; buffer[0] = (byte)value; buffer[1] = (byte)(value >> 8); buffer[2] = (byte)(value >> 16); buffer[3] = (byte)(value >> 24); return(OutStream.WriteAsync(buffer, 0, 4, cancellationToken)); }
public Task WriteAsync(long value, CancellationToken cancellationToken) { byte[] buffer = Buffer; buffer[0] = (byte)value; buffer[1] = (byte)(value >> 8); buffer[2] = (byte)(value >> 16); buffer[3] = (byte)(value >> 24); buffer[4] = (byte)(value >> 32); buffer[5] = (byte)(value >> 40); buffer[6] = (byte)(value >> 48); buffer[7] = (byte)(value >> 56); return(OutStream.WriteAsync(buffer, 0, 8, cancellationToken)); }
/// <summary> /// Accepts Base64 String data converts it to the binary stream /// </summary> /// <param name="text">A Snippet of Base64 text to be written to the stream</param> /// <returns>The number of characters consumed by the conversion (which may NOT be the whole string)</returns> public async Task <int> WriteString(string text) { var textToWrite = unwritten + text; var charsToWrite = 4 * ((int)(textToWrite.Length / 4)); var newChars = Convert.FromBase64String(textToWrite.Substring(0, charsToWrite)); unwritten = (charsToWrite < textToWrite.Length) ? textToWrite.Substring(charsToWrite) : ""; if (!Ignore) { await OutStream.WriteAsync(newChars, 0, newChars.Length); } return(charsToWrite); }
protected virtual async Task WriteHeaderAsync(string name, DateTime lastModificationTime, long count, string userName, string groupName, int mode) { var tarHeader = new UsTarHeader() { FileName = name, LastModification = lastModificationTime, SizeInBytes = count, UserId = userName.GetHashCode(), UserName = userName, GroupId = groupName.GetHashCode(), GroupName = groupName, Mode = mode }; await OutStream.WriteAsync(tarHeader.GetHeaderValue(), 0, tarHeader.HeaderSize); }
protected override async Task WriteHeaderAsync(string name, DateTime lastModificationTime, long count, int userId, int groupId, int mode, EntryType entryType) { var tarHeader = new UsTarHeader() { FileName = name, LastModification = lastModificationTime, SizeInBytes = count, UserId = userId, UserName = Convert.ToString(userId, 8), GroupId = groupId, GroupName = Convert.ToString(groupId, 8), Mode = mode, EntryType = entryType }; await OutStream.WriteAsync(tarHeader.GetHeaderValue(), 0, tarHeader.HeaderSize); }
/// <summary> /// Start service loop. /// </summary> private async Task StartAsyncSend() { Running = true; while (Running) { if (OutStream == null || !OutStream.CanWrite) { Thread.Sleep(100); continue; } try { if (AudioQueue.Count > 0) { byte[] mixed = new byte[AudioHelpers.BUFFER_SIZE * AudioHelpers.CHANNEL_COUNT]; for (int i = 0; i < AudioHelpers.FRAME_SAMPLES; ++i) { int sample = 0; foreach (var audioPair in AudioQueue) { var session = audioPair.Value; if (session.State == ReproductionState.Paused) { continue; } if (session.State == ReproductionState.Stopped) { session.CloseReproduction(); } if (session.State == ReproductionState.Closed || session.EndOfStream) { AudioQueue.TryRemove(audioPair.Key, out var e); continue; } double volume = Math.Max(Math.Min((session.Source?.Volume ?? DefaultAudioSource.Instance.Volume) / 100, 1), 0); double gain = (session.Source?.Gain ?? DefaultAudioSource.Instance.Gain) + 1; byte[] buffer = new byte[AudioHelpers.SAMPLE_SIZE]; if (session.Read(buffer, 0, AudioHelpers.SAMPLE_SIZE) > 0) { sample += (Int32)(AudioHelpers.GetInt16(buffer, 0, true) * volume * gain); } } short sampleValue = (short)Math.Min(Math.Max(short.MinValue, sample), short.MaxValue); AudioHelpers.GetBytes(sampleValue, mixed, i * AudioHelpers.SAMPLE_SIZE, true); } // Send the buffer to Discord await OutStream.WriteAsync(mixed, 0, AudioHelpers.FRAME_SAMPLES *AudioHelpers.CHANNEL_COUNT); } else { // Flush stream await OutStream.FlushAsync(); Thread.Sleep(100); } } catch (Exception e) { } } await Task.CompletedTask; }
public void Start() { Stop(); Running = true; _cancellationTokenSource = new CancellationTokenSource(); ReadFinished = false; _readTask = Task.Run(async() => { while (Running && _cancellationTokenSource?.IsCancellationRequested == false) { try { if (InStream.CanRead) { AudioChunk chunk = new AudioChunk(BufferReadSize); int bytesRead = await InStream.ReadAsync(chunk.Memory, _cancellationTokenSource.Token).ConfigureAwait(false); if (bytesRead > 0) { chunk.Length = bytesRead; // Wait for the dequeue, comparing in megabytes. while (Running && (Queue.Count * (BufferReadSize * 0.000001)) > BufferLimit) { await Task.Delay(100, _cancellationTokenSource?.Token ?? CancellationToken.None).ConfigureAwait(false); } Queue.Enqueue(chunk); } else { Log.Debug("AudioBuffer: Read EOF"); break; } } else { Log.Error("AudioBuffer: Could not read InStream."); await Task.Delay(25).ConfigureAwait(false); } } catch (OperationCanceledException) { return; } catch (Exception ex) { Log.Error($"AudioBuffer | {ex}"); } } ReadFinished = true; }, _cancellationTokenSource.Token); _writeTask = Task.Run(async() => { while (Running && _cancellationTokenSource?.IsCancellationRequested == false) { if (ReadFinished && Queue.IsEmpty) { break; } try { if (Queue.TryDequeue(out var audioChunk)) { using (audioChunk) { if (OutStream.CanWrite) { // We're required to process the chunks in the write task, it's far slower which allows us to change the volume while it's still playing. if (ProcessBuffer != null) { var bytes = audioChunk.Memory; if (audioChunk.Length != audioChunk.Memory.Length) { bytes = audioChunk.Memory.Part(0, audioChunk.Length, false).ToArray(); } var processedBytes = ProcessBuffer?.Invoke(bytes); processedBytes.CopyTo(audioChunk.Memory, 0); audioChunk.Length = processedBytes.Length; } await OutStream.WriteAsync(audioChunk.Memory, 0, audioChunk.Length, _cancellationTokenSource.Token); } else { Log.Error("AudioBuffer: Could not write to OutStream."); await Task.Delay(25).ConfigureAwait(false); } } } } catch (OperationCanceledException) { return; } catch (Exception ex) { Log.Error($"AudioBuffer | {ex.Message}"); Log.Debug($"AudioBuffer | {ex}"); await Task.Delay(25).ConfigureAwait(false); } } }, _cancellationTokenSource.Token); }
public Task WriteAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken) { return(OutStream.WriteAsync(buffer, index, count, cancellationToken)); }
public Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) { return(OutStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken)); }
public Task WriteAsync(byte value, CancellationToken cancellationToken) { Debug.Assert(value <= 18); return(OutStream.WriteAsync(ByteValueBuffer, value, 1, cancellationToken)); }
public Task WriteAsync(bool value, CancellationToken cancellationToken) { return(OutStream.WriteAsync(ByteValueBuffer, value ? 1 : 0, 1, cancellationToken)); }