protected override async Task <int> DoReadAsync(byte[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { while (_bytesInBuffer < count) { var byteCount = await _clip.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken); if (byteCount == 0) { break; } // Write to buffer stream and seek back the number of bytes we wrote var current = _bufferStream.Position; _bufferStream.Seek(0, SeekOrigin.End); await _bufferStream.WriteAsync(_buffer, 0, byteCount, cancellationToken); _bufferStream.Seek(current, SeekOrigin.Begin); _bytesInBuffer += byteCount; } var bytesToRead = (int)Math.Min(_bytesInBuffer, count); _bytesInBuffer -= bytesToRead; return(await _bufferStream.ReadAsync(outputBuffer, offset, bytesToRead, cancellationToken)); }
protected override async Task <int> DoReadAsync(byte[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { void _complete() { _ = _currentClip.DisposeAsync(); _playlist.Remove(_currentClip); _currentClip = null; OnClipCompleted?.Invoke(this, _currentClip); } // Check if the current song should be skipped if (_shouldSkip) { _shouldSkip = false; _complete(); } // Check if any items need to start preparing if (_playlist.Count(p => (p.IsReady || p.IsPreparing) && p != _currentClip) == 0) { var toPrepare = _playlist.FirstOrDefault(p => !p.IsReady && !p.IsPreparing); if (toPrepare != null) { _ = toPrepare.PrepareAsync(); } } // Set the current clip to the next clip if necessary if (_currentClip == null) { _currentClip = _playlist.FirstOrDefault(p => p.IsReady); } if (_currentClip == null) { return(0); } var byteCount = await _currentClip.ReadAsync(outputBuffer, offset, count, cancellationToken); if (byteCount == 0) { _complete(); } return(byteCount); }
public static async Task <int> ReadAsync(this Clip clip, short[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { var buffer = new byte[count * 2]; var bytesRead = await clip.ReadAsync(buffer, 0, buffer.Length, cancellationToken); for (int sample = 0; sample < bytesRead / 2; sample++) { int i = sample * 2; short b1 = (short)((buffer[i + 1] & 0xff) << 8); short b2 = (short)(buffer[i] & 0xff); outputBuffer[sample + offset] = (short)(b1 | b2); } return(bytesRead / 2); }
protected override async Task <int> DoReadAsync(byte[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { var ratio = _inputSampleRate / (double)_outputSampleRate; var buffer = new byte[(int)Math.Ceiling(count * ratio)]; var byteCount = await _clip.ReadAsync(buffer, 0, buffer.Length, cancellationToken); var outputByteCount = (int)(byteCount / ratio); for (int sample = 0; sample < outputByteCount / 2; sample++) { var i = sample * 2; var j = (int)(sample * ratio) * 2; outputBuffer[i] = buffer[j]; outputBuffer[i + 1] = buffer[j + 1]; } return(outputByteCount); }
protected override async Task DoPrepareAsync() { await _clip.PrepareAsync(); var cts = new CancellationTokenSource(); while (true) { var buffer = new byte[2880]; var byteCount = await _clip.ReadAsync(buffer, 0, buffer.Length, cts.Token); if (byteCount == 0) { break; } await _stream.WriteAsync(buffer, 0, byteCount, cts.Token); } }
protected override async Task <int> DoReadAsync(byte[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { var byteCount = await _clip.ReadAsync(outputBuffer, offset, count, cancellationToken); for (int i = offset; i < offset + byteCount; i += 2) { short b1 = (short)((outputBuffer[i + 1] & 0xff) << 8); short b2 = (short)(outputBuffer[i] & 0xff); short data = (short)(b1 | b2); float sample = data / (float)short.MaxValue; data = (short)(sample * short.MaxValue * _volume); outputBuffer[i] = (byte)data; outputBuffer[i + 1] = (byte)(data >> 8); } return(byteCount); }
protected override async Task <int> DoReadAsync(byte[] outputBuffer, int offset, int count, CancellationToken cancellationToken) { async Task <int> waitAndReturn(CancellationToken cancellationToken) { await cancellationToken.WhenCancelled(); throw new OperationCanceledException(); } while (!cancellationToken.IsCancellationRequested && _bytesInBuffer < count) { var workaround = await Task.WhenAny( _clip.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken), waitAndReturn(cancellationToken) ); var byteCount = await workaround; if (byteCount == 0) { break; } // Write to buffer stream and seek back the number of bytes we wrote var current = _bufferStream.Position; _bufferStream.Seek(0, SeekOrigin.End); await _bufferStream.WriteAsync(_buffer, 0, byteCount, cancellationToken); _bufferStream.Seek(current, SeekOrigin.Begin); _bytesInBuffer += byteCount; } cancellationToken.ThrowIfCancellationRequested(); var bytesToRead = (int)Math.Min(_bytesInBuffer, count); _bytesInBuffer -= bytesToRead; return(await _bufferStream.ReadAsync(outputBuffer, offset, bytesToRead, cancellationToken)); }