private void SendAudioData(IAudioClient audioClient, PlayRequest request) { try { var file = request.File; var cancellationToken = request.TokenSource.Token; using (var reader = File.OpenRead(file)) { byte[] buffer = new byte[BLOCK_SIZE]; int byteCount; while ((byteCount = reader.Read(buffer, 0, BLOCK_SIZE)) > 0) { if (cancellationToken.IsCancellationRequested) { audioClient.Clear(); return; } audioClient.Send(buffer, 0, byteCount); } } audioClient.Wait(); } catch (Exception ex) { Logger.Error(ex.Message, ex); } }
private async Task SendSound(string song) { if (!_playing) { _vclient = await _client.GetService <AudioService>().Join(channel); _playing = true; } _skipThis = false; await Task.Run(() => { int channelCount = _client.GetService <AudioService>().Config.Channels; WaveFormat outFormat = new WaveFormat(48000, 16, channelCount); AudioFileReader r = new AudioFileReader(song); using (MediaFoundationResampler resampler = new MediaFoundationResampler(r, outFormat)) { resampler.ResamplerQuality = 60; int blockSize = outFormat.AverageBytesPerSecond / 50; byte[] buffer = new byte[blockSize]; int byteCount; while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0 && _playing == true) { r.Volume = volume; if (byteCount < blockSize) { // Incomplete Frame for (int i = byteCount; i < blockSize; i++) { buffer[i] = 0; if (_skipThis) { _vclient.Clear(); break; } } } _vclient.Send(buffer, 0, blockSize); _vclient.Wait(); } GetNextSong(); } }); }
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var bufferTask = BufferSong(cancelToken).ConfigureAwait(false); var bufferAttempts = 0; const int waitPerAttempt = 500; var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9; while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes) { await Task.Delay(waitPerAttempt, cancelToken).ConfigureAwait(false); } cancelToken.ThrowIfCancellationRequested(); Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}"); const int blockSize = 3840; var attempt = 0; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); byte[] buffer = new byte[blockSize]; var read = songBuffer.Read(buffer, blockSize); unchecked { bytesSent += (ulong)read; } if (read == 0) { if (attempt++ == 20) { voiceClient.Wait(); Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]"); break; } else { await Task.Delay(100, cancelToken).ConfigureAwait(false); } } else { attempt = 0; } while (this.MusicPlayer.Paused) { await Task.Delay(200, cancelToken).ConfigureAwait(false); } buffer = AdjustVolume(buffer, MusicPlayer.Volume); voiceClient.Send(buffer, 0, read); } Console.WriteLine("Awiting buffer task"); await bufferTask; Console.WriteLine("Buffer task done."); voiceClient.Clear(); cancelToken.ThrowIfCancellationRequested(); }
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); SongBuffer sb = new SongBuffer(filename, SongInfo, skipTo); var bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false); var inStream = new FileStream(sb.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);; bytesSent = 0; try { var attempt = 0; var prebufferingTask = CheckPrebufferingAsync(inStream, sb, cancelToken); var sw = new Stopwatch(); sw.Start(); var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken)); if (t != prebufferingTask) { Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream."); return; } else if (prebufferingTask.IsCanceled) { Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream."); return; } sw.Stop(); Console.WriteLine("Prebuffering successfully completed in " + sw.Elapsed); const int blockSize = 3840; byte[] buffer = new byte[blockSize]; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); var read = inStream.Read(buffer, 0, buffer.Length); //await inStream.CopyToAsync(voiceClient.OutputStream); unchecked { bytesSent += (ulong)read; } if (read < blockSize) { if (sb.IsNextFileReady()) { inStream.Dispose(); inStream = new FileStream(sb.GetNextFile(), FileMode.Open, FileAccess.Read, FileShare.Write); read += inStream.Read(buffer, read, buffer.Length - read); attempt = 0; } if (read == 0) { if (sb.BufferingCompleted) { break; } if (attempt++ == 20) { voiceClient.Wait(); MusicPlayer.SongCancelSource.Cancel(); break; } else { await Task.Delay(100, cancelToken).ConfigureAwait(false); } } else { attempt = 0; } } else { attempt = 0; } while (this.MusicPlayer.Paused) { await Task.Delay(200, cancelToken).ConfigureAwait(false); } buffer = AdjustVolume(buffer, MusicPlayer.Volume); voiceClient.Send(buffer, 0, read); } } finally { await bufferTask; await Task.Run(() => voiceClient.Clear()); if (inStream != null) { inStream.Dispose(); } Console.WriteLine("l"); sb.CleanFiles(); } }
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var bufferTask = BufferSong(cancelToken).ConfigureAwait(false); var bufferAttempts = 0; const int waitPerAttempt = 500; var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9; while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes) { await Task.Delay(waitPerAttempt, cancelToken); } cancelToken.ThrowIfCancellationRequested(); Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}"); const int blockSize = 3840; var attempt = 0; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); byte[] buffer = new byte[blockSize]; var read = songBuffer.Read(buffer, blockSize); unchecked { bytesSent += (ulong)read; } if (read == 0) if (attempt++ == 20) { voiceClient.Wait(); Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]"); break; } else await Task.Delay(100, cancelToken); else attempt = 0; while (this.MusicPlayer.Paused) await Task.Delay(200, cancelToken); buffer = AdjustVolume(buffer, MusicPlayer.Volume); voiceClient.Send(buffer, 0, read); } Console.WriteLine("Awiting buffer task"); await bufferTask; Console.WriteLine("Buffer task done."); voiceClient.Clear(); cancelToken.ThrowIfCancellationRequested(); }
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var bufferTask = new ConfiguredTaskAwaitable(); try { bufferTask = BufferSong(cancelToken).ConfigureAwait(false); } catch (Exception ex) { var clr = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"ERR BUFFER START : {ex.Message}\n{ex}"); Console.ForegroundColor = clr; } var bufferAttempts = 0; const int waitPerAttempt = 500; var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9; while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes) { await Task.Delay(waitPerAttempt, cancelToken); } cancelToken.ThrowIfCancellationRequested(); Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}"); const int blockSize = 3840; var attempt = 0; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); byte[] buffer = new byte[blockSize]; var read = songBuffer.Read(buffer, blockSize); if (read == 0) { if (attempt++ == 20) { Console.WriteLine("Waiting to empty out buffer."); voiceClient.Wait(); Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]"); break; } else { await Task.Delay(100, cancelToken); } } else { attempt = 0; } while (this.MusicPlayer.Paused) { await Task.Delay(200, cancelToken); } buffer = AdjustVolume(buffer, MusicPlayer.Volume); voiceClient.Send(buffer, 0, read); } await bufferTask; voiceClient.Clear(); cancelToken.ThrowIfCancellationRequested(); }
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); SongBuffer sb = new SongBuffer(filename, SongInfo, skipTo); var bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false); var inStream = new FileStream(sb.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); ; bytesSent = 0; try { var attempt = 0; var prebufferingTask = CheckPrebufferingAsync(inStream, sb, cancelToken); var sw = new Stopwatch(); sw.Start(); var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken)); if (t != prebufferingTask) { Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream."); return; } else if(prebufferingTask.IsCanceled) { Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream."); return; } sw.Stop(); Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed); const int blockSize = 3840; byte[] buffer = new byte[blockSize]; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); var read = inStream.Read(buffer, 0, buffer.Length); //await inStream.CopyToAsync(voiceClient.OutputStream); unchecked { bytesSent += (ulong)read; } if (read < blockSize) { if (sb.IsNextFileReady()) { inStream.Dispose(); inStream = new FileStream(sb.GetNextFile(), FileMode.Open, FileAccess.Read, FileShare.Write); read += inStream.Read(buffer, read, buffer.Length - read); attempt = 0; } if (read == 0) { if (sb.BufferingCompleted) break; if (attempt++ == 20) { voiceClient.Wait(); MusicPlayer.SongCancelSource.Cancel(); break; } else await Task.Delay(100, cancelToken).ConfigureAwait(false); } else attempt = 0; } else attempt = 0; while (this.MusicPlayer.Paused) await Task.Delay(200, cancelToken).ConfigureAwait(false); buffer = AdjustVolume(buffer, MusicPlayer.Volume); voiceClient.Send(buffer, 0, read); } } finally { await bufferTask; await Task.Run(() => voiceClient.Clear()); if(inStream != null) inStream.Dispose(); Console.WriteLine("l"); sb.CleanFiles(); } }
public void PlaySound(AudioService audioService, IAudioClient audioClient, TrackRequest trackRequest) { var channels = audioService.Config.Channels; var timePlayed = 0; var outFormat = new WaveFormat(48000, 16, channels); SetVolumeOfCurrentTrack(trackRequest.Volume); using (var audioFileStream = new MediaFoundationReader(trackRequest.Track.Path)) using (var waveChannel32 = new WaveChannel32(audioFileStream, (_volumeOverride > 0 ? _volumeOverride : _volume) * 0.2f, 0f) { PadWithZeroes = false }) using (var effectStream = new EffectStream(waveChannel32)) using (var blockAlignmentStream = new BlockAlignReductionStream(effectStream)) using (var resampler = new MediaFoundationResampler(blockAlignmentStream, outFormat)) { resampler.ResamplerQuality = 60; ApplyEffects(waveChannel32, effectStream, trackRequest); // Establish the size of our AudioBuffer var blockSize = outFormat.AverageBytesPerSecond / 50; var buffer = new byte[blockSize]; int byteCount; // Read audio into our buffer, and keep a loop open while data is present while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) { waveChannel32.Volume = (_volumeOverride > 0 ? _volumeOverride : _volume) * 0.2f; // Limit play length (--length) timePlayed += byteCount * 1000 / outFormat.AverageBytesPerSecond; if (trackRequest.TimeLimit > 0 && timePlayed > trackRequest.TimeLimit) { break; } if (byteCount < blockSize) { // Incomplete Frame for (var i = byteCount; i < blockSize; i++) { buffer[i] = 0; } } if (audioClient.State == ConnectionState.Disconnected || Stop) { break; } // Send the buffer to Discord try { audioClient.Send(buffer, 0, blockSize); } catch (Exception) { break; } } MyLogger.WriteLine("Voice finished enqueuing", ConsoleColor.Green); } if (Stop) { audioClient.Clear(); Stop = false; } audioClient.Wait(); }
public async void SendOnlineAudio(CommandEventArgs e, string pathOrUrl) { try { await joinVoiceChannel(e); } catch (Exception ex) { Console.WriteLine("WARNING: Bot failed!"); e.Channel.SendMessage("ERROR: Bot failed"); return; } if (!isInSameVoice(e)) { e.Channel.SendMessage("You are not in the same voice as me!"); return; } YouTubeVideo ytVideo = new YouTubeVideo(pathOrUrl, e.User.Name); //Couldn't find a video so do not add if (ytVideo.title == "") { e.Channel.SendMessage("Could not find video!"); return; } if (playingSong) { queue.Enqueue(ytVideo); sendMessage(ytVideo.requester + " added `" + ytVideo.title + "` **" + ytVideo.duration + "** to the queue! **[" + queue.Count + "]**"); return; } currentSong = ytVideo; if (_vClient == null) { e.Channel.SendMessage("You are not in a voice channel!"); return; } playingSong = true; sendMessage("Playing `" + currentSong.title + "` **" + currentSong.duration + "**"); var process = Process.Start(new ProcessStartInfo { // FFmpeg requires us to spawn a process and hook into its stdout, so we will create a Process FileName = "cmd.exe", Arguments = "/C youtube-dl.exe -f 140 -o - " + pathOrUrl + " -q -i | ffmpeg.exe -i pipe:0 -f s16le -ar 48000 -ac 2 pipe:1 -af \"volume=" + volume + "\" -loglevel quiet", // Next, we tell it to output 16-bit 48000Hz PCM, over 2 channels, to stdout. UseShellExecute = false, RedirectStandardOutput = true, // Capture the stdout of the process RedirectStandardError = false, }); //Thread.Sleep(1500); // Sleep for a few seconds to FFmpeg can start processing data. int blockSize = 3840; // The size of bytes to read per frame; 1920 for mono byte[] buffer = new byte[blockSize]; int byteCount; while (playingSong) // Loop forever, so data will always be read { if (!playingSong || process.HasExited) { Console.WriteLine("task canceled"); break; } byteCount = process.StandardOutput.BaseStream // Access the underlying MemoryStream from the stdout of FFmpeg .Read(buffer, 0, blockSize); // Read stdout into the buffer if (byteCount == 0) // FFmpeg did not output anything { break; // Break out of the while(true) loop, since there was nothing to read. } try { _vClient.Send(buffer, 0, byteCount); // Send our data to Discord } catch (OperationCanceledException ex) { Console.WriteLine("Operation cancelled!"); break; } } _vClient.Clear(); try { _vClient.Wait(); // Wait for the Voice Client to finish sending data, as ffMPEG may have already finished buffering out a song, and it is unsafe to return now. }catch (OperationCanceledException ex) { Console.WriteLine("Operation canceled"); } if (!process.HasExited) { process.Kill(); process.Dispose(); Console.WriteLine("Killed process"); } //set current votes to 0, if a vote was underway, but not enough voted to skip votes.Clear(); playingSong = false; if (!queue.Any()) { sendMessage("No songs in queue! Disconnecting..."); leaveVoiceChannel(); return; } string video = queue.First().url; queue.Dequeue(); //Thread.Sleep(1000); //Sleep for a sec so it can stop music //Play next song //await Task.Run(() => SendOnlineAudio(e, video), ct); SendOnlineAudio(e, video); }