/// <summary> /// This event is triggered when the sound card needs more samples to be /// played. When this happens, we have to feed it additional frames so it /// can continue playing. /// </summary> /// private void output_NewFrameRequested(object sender, NewFrameRequestedEventArgs e) { this.decoder.FillNewFrame(e); }
/// <summary> /// This event is triggered when the sound card needs more samples to be /// played. When this happens, we have to feed it additional frames so it /// can continue playing. /// </summary> /// private void output_NewFrameRequested(object sender, NewFrameRequestedEventArgs e) { // This is the next frame index e.FrameIndex = decoder.Position; // Attempt to decode the requested number of frames from the stream Signal signal = decoder.Decode(e.Frames); if (signal == null) { // We could not get the requested number of frames. When // this happens, this is an indication we need to stop. e.Stop = true; return; } // Inform the number of frames // actually read from source e.Frames = signal.Length; // Copy the signal to the buffer signal.CopyTo(e.Buffer); }
private void output_NewFrameRequested(object sender, NewFrameRequestedEventArgs e) { e.FrameIndex = decoder.Position; // Attempt to decode the requested number of frames from the stream Signal signal = decoder.Decode(e.Frames); if (signal == null) { e.Stop = true; } else { // Inform the number of frames // actually read from source e.Frames = signal.Length; // Copy the signal to the buffer signal.CopyTo(e.Buffer); } }
/// <summary> /// Worker thread. /// </summary> /// private void WorkerThread() { int samples = bufferSize / sizeof(float); try { // The first write should fill the entire buffer. var request = new NewFrameRequestedEventArgs(samples); NewFrameRequested.Invoke(this, request); buffer.Write(request.Buffer, 0, LockFlags.None); // The buffer starts playing. buffer.Play(0, PlayFlags.Looping); int framesPlayed = request.FrameIndex; int lastNotificationLocation = 0; bool requestedToStop = false; while (!stop) { int positionIndex = WaitHandle.WaitAny(waitHandles); if (stop) break; if (positionIndex == firstHalfBufferIndex || positionIndex == secondHalfBufferIndex) { if (requestedToStop) break; // When the first half of the buffer has finished // playing and we have just started playing the // second half, we will write the next samples in // the first half of the buffer again. // When the second half of the buffer has finished // playing, the first half of the buffer will // start playing again (since this is a circular // buffer). At this time, we can write the next // samples in the second half of the buffer. request.Frames = samples / 2; NewFrameRequested(this, request); requestedToStop = request.Stop; int offset = (positionIndex == firstHalfBufferIndex) ? 0 : bufferSize / 2; buffer.Write(request.Buffer, 0, request.Frames, offset, LockFlags.None); } if (positionIndex != secondHalfBufferIndex) { // Notify progress int currentBufferLocation = notifications[positionIndex].Offset; if (lastNotificationLocation >= currentBufferLocation) lastNotificationLocation = -(bufferSize - lastNotificationLocation); int delta = (currentBufferLocation - lastNotificationLocation); framesPlayed += delta / sizeof(float); lastNotificationLocation = currentBufferLocation; OnFramePlayingStarted(new PlayFrameEventArgs(framesPlayed, delta)); } } } catch (Exception ex) { if (AudioOutputError != null) AudioOutputError(this, new AudioOutputErrorEventArgs(ex.Message)); else throw; } finally { buffer.Stop(); OnStopped(EventArgs.Empty); } }
public void FillNewFrame(NewFrameRequestedEventArgs frameRequestArgs) { // This is the next frame index frameRequestArgs.FrameIndex = this.decoder.Position; // Attempt to decode the requested number of frames from the stream Signal signal = this.decoder.Decode(frameRequestArgs.Frames); if (signal == null) { // We could not get the requested number of frames. When // this happens, this is an indication we need to stop. frameRequestArgs.Stop = true; return; } // Inform the number of frames // actually read from source frameRequestArgs.Frames = signal.Length; // Copy the signal to the buffer signal.CopyTo(frameRequestArgs.Buffer); }