简体   繁体   中英

Beep in C# .NET application on server side

To debug a firewall delay issue I need an application that will produce a beep on server side when it detects an HTTP GET request.

This code (test.ashx):

<%@ WebHandler Language="C#" Class="TestHandler" %>

using System;
using System.Web;

public class TestHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        HttpResponse Response = context.Response;
        try
        {
            Response.Write("Before beep");
            Console.Beep();
            Response.Write("After beep");
        }
        catch (Exception ex)
        {
            Response.Write(ex.Message + "<br />\n" + ex.InnerException.Message);
        }
    }

    public bool IsReusable { get { return false; } }
}

produces sound only when debugging in IIS Express. After moving the web app to IIS, the sound disappears.

The three easy ways of producing a sound are System.Console.Beep() , System.Media.SoundPlayer , and System.Media.SystemSounds.Beep() .

Unfortunately, these methods only work in desktop applications, and won't work in service applications. When ASP.Net apps are run under IIS Express (a desktop app), these sound methods work. However, when ASP.Net apps are run under the IIS service, the sound methods don't work.

System.Console.Beep() ultimately calls the kernel32.dll Beep() function. It's restricted to desktop apps only (scroll down to the Requirements section).

Same for System.Media.SoundPlayer and System.Media.SystemSounds.Beep(). They call the kernel32.dll MessageBeep() and the winmm.dll PlaySound() functions, respectively. They, too, are restricted to desktop apps.

One way to get sounds to play in a service is use NAudio . It's easy to install via NuGet.

This chunk of code is the only way I could get the sound to play. It has to be played on a separate worker thread, and the execution of the worker thread needs to be paused to let the .wav file finish playing.

using System;
using System.Diagnostics;
using System.Threading;

using NAudio.Dsp;
using NAudio.Wave;

...

protected void Button1_Click(object sender, EventArgs e)
{
  var waveFilename = @"c:\Windows\Media\tada.wav";

  /* Trying to play the .wav file on the main thread
     doesn't seem to work. */
  ThreadPool.QueueUserWorkItem(
    (state) =>
    {
      using (var audioPlayback = new AudioPlayback())
      {
        audioPlayback.Load(waveFilename);
        audioPlayback.Play(); // Asynchronous.

        /* Need to sleep for the approximate length of .wav file,
           otherwise no sound is produced because of the
           asynchronous Play() call. */
        Thread.Sleep(2000);
      }
    });
}

Here's the supporting code taken from code in NAudio's NAudioWPFDemo project:

public class MaxSampleEventArgs : EventArgs
{
  [DebuggerStepThrough]
  public MaxSampleEventArgs(float minValue, float maxValue)
  {
    this.MaxSample = maxValue;
    this.MinSample = minValue;
  }
  public float MaxSample { get; private set; }
  public float MinSample { get; private set; }
}

public class FftEventArgs : EventArgs
{
  [DebuggerStepThrough]
  public FftEventArgs(Complex[] result)
  {
    this.Result = result;
  }
  public Complex[] Result { get; private set; }
}

public class SampleAggregator : ISampleProvider
{
  // volume
  public event EventHandler<MaxSampleEventArgs> MaximumCalculated;
  private float maxValue;
  private float minValue;
  public int NotificationCount { get; set; }
  int count;

  // FFT
  public event EventHandler<FftEventArgs> FftCalculated;
  public bool PerformFFT { get; set; }
  private readonly Complex[] fftBuffer;
  private readonly FftEventArgs fftArgs;
  private int fftPos;
  private readonly int fftLength;
  private int m;
  private readonly ISampleProvider source;

  private readonly int channels;

  public SampleAggregator(ISampleProvider source, int fftLength = 1024)
  {
    channels = source.WaveFormat.Channels;
    if (!IsPowerOfTwo(fftLength))
      throw new ArgumentException("FFT Length must be a power of two");

    this.m = (int) Math.Log(fftLength, 2.0);
    this.fftLength = fftLength;
    this.fftBuffer = new Complex[fftLength];
    this.fftArgs = new FftEventArgs(fftBuffer);
    this.source = source;
  }

  private bool IsPowerOfTwo(int x)
  {
    return (x & (x - 1)) == 0;
  }

  public void Reset()
  {
    count = 0;
    maxValue = minValue = 0;
  }

  private void Add(float value)
  {
    if (PerformFFT && FftCalculated != null)
    {
      fftBuffer[fftPos].X = (float) (value * FastFourierTransform.HammingWindow(fftPos, fftLength));
      fftBuffer[fftPos].Y = 0;
      fftPos++;
      if (fftPos >= fftBuffer.Length)
      {
        fftPos = 0;
        // 1024 = 2^10
        FastFourierTransform.FFT(true, m, fftBuffer);
        FftCalculated(this, fftArgs);
      }
    }

    maxValue = Math.Max(maxValue, value);
    minValue = Math.Min(minValue, value);
    count++;
    if (count >= NotificationCount && NotificationCount > 0)
    {
      if (MaximumCalculated != null)
        MaximumCalculated(this, new MaxSampleEventArgs(minValue, maxValue));

      Reset();
    }
  }

  public WaveFormat WaveFormat { get { return source.WaveFormat; } }

  public int Read(float[] buffer, int offset, int count)
  {
    var samplesRead = source.Read(buffer, offset, count);

    for (int n = 0; n < samplesRead; n += channels)
      Add(buffer[n + offset]);

    return samplesRead;
  }
}

public class AudioPlayback : IDisposable
{
  private IWavePlayer _playbackDevice;
  private WaveStream _fileStream;

  public void Load(string fileName)
  {
    Stop();
    CloseFile();
    EnsureDeviceCreated();
    OpenFile(fileName);
  }

  private void CloseFile()
  {
    if (_fileStream != null)
    {
      _fileStream.Dispose();
      _fileStream = null;
    }
  }

  private void OpenFile(string fileName)
  {
    try
    {
      var inputStream = new AudioFileReader(fileName);
      _fileStream = inputStream;
      var aggregator = new SampleAggregator(inputStream);
      aggregator.NotificationCount = inputStream.WaveFormat.SampleRate / 100;
      aggregator.PerformFFT = true;
      _playbackDevice.Init(aggregator);
    }
    catch
    {
      CloseFile();
      throw;
    }
  }

  private void EnsureDeviceCreated()
  {
    if (_playbackDevice == null)
      CreateDevice();
  }

  private void CreateDevice()
  {
    _playbackDevice = new WaveOut { DesiredLatency = 200 };
  }

  public void Play()
  {
    if (_playbackDevice != null && _fileStream != null && _playbackDevice.PlaybackState != PlaybackState.Playing)
      _playbackDevice.Play();
  }

  public void Pause()
  {
    if (_playbackDevice != null)
      _playbackDevice.Pause();
  }

  public void Stop()
  {
    if (_playbackDevice != null)
      _playbackDevice.Stop();

    if (_fileStream != null)
      _fileStream.Position = 0;
  }

  public void Dispose()
  {
    Stop();
    CloseFile();
    if (_playbackDevice != null)
      _playbackDevice.Dispose();
  }
}

试试这个System.Media.SystemSounds.Beep.Play();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM