【问题标题】:How Can I Play without file?没有文件怎么玩?
【发布时间】:2012-11-19 13:23:21
【问题描述】:

我想在不从文件加载/流式传输的情况下播放响铃警报。

我可以在代码中嵌入它的信号或音调吗?我正在使用NAudio

我的目的是通过删除 IO 操作来提高性能。

我不想使用嵌入式资源。 只有我想在代码中生成响铃警报。

【问题讨论】:

  • 如果您可以将文件作为资源嵌入,只需使用该资源的流。
  • 感谢您的回复。事实上,我不想使用任何文件。因为性能快。我想使用诸如 RTTTL 代码之类的文本代码来作为已接电话响铃。

标签: c# .net audio naudio


【解决方案1】:

使用 NAudio,您有以下选择:

  • 播放流中的文件(在内存中)。您在其他答案中有此代码,实际上您甚至不需要 NAudio 来完成此任务,因为 System.Media.SoundPlayer 就足够了。
  • 生成将要播放的信号(无需将其保存在某处)。
  • 播放一串声音命令(就像我们在 good old times 中使用 BASIC 中的 play 所做的那样)。

产生信号

第一个案例的示例来自 MSDN 上的 Charles Petzold 文章(但也可以查看 NAudio documentation):

class SineWaveOscillator : WaveProvider16 {
  double phaseAngle;

  public SineWaveOscillator(int sampleRate): 
    base(sampleRate, 1) {
  }

  public double Frequency { set; get; }
  public short Amplitude { set; get; }

  public override int Read(short[] buffer, int offset, 
    int sampleCount) {

    for (int index = 0; index < sampleCount; index++) {
      buffer[offset + index] = 
        (short)(Amplitude * Math.Sin(phaseAngle));
      phaseAngle += 
        2 * Math.PI * Frequency / WaveFormat.SampleRate;

      if (phaseAngle > 2 * Math.PI)
        phaseAngle -= 2 * Math.PI;
    }
    return sampleCount;
  }
}

然后播放音调的代码很简单:

SineWaveOscillator osc = new SineWaveOscillator(44100);
osc.Frequency = 440;
osc.Amplitude = 8192;

WaveOut waveOut = new WaveOut();
waveOut.Init(osc);
waveOut.Play();

播放 MIDI

对于第二种情况(播放一串 MIDI 命令),请再次查看另一个 Charles Petzold article。他的MidiStringPlayer 类提供了你需要的一切(但你可能需要去掉 WPF 代码才能在你想要的地方使用它)。使用 NAudio 播放 MIDI 的基本代码是:

using (MidiOut midiOut = new MidiOut(0))
{
    midiOut.Send(MidiMessage.StartNote(60, 127, 0).RawData);
    Thread.Sleep(1000);
    midiOut.Send(MidiMessage.StopNote(60, 0, 0).RawData);
    Thread.Sleep(1000);
}

如果您真的需要从字符串中播放音符,那么您必须对其进行解析,代码太长,无法在此处发布,但在链接中您会找到所有内容。

【讨论】:

    【解决方案2】:

    NAudio 解决方案如下所示

    Test.Properties.Resources.aaa 这是mp3的路径

    using (var ms = new MemoryStream(Test.Properties.Resources.aaa))
    using (var rdr = new NAudio.Wave.Mp3FileReader(ms))
    using (var wavStream = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(rdr))
    using (var baStream = new NAudio.Wave.BlockAlignReductionStream(wavStream))
    using (var waveOut = new NAudio.Wave.WaveOut(NAudio.Wave.WaveCallbackInfo.FunctionCallback())) {
       waveOut.Init(baStream);
       waveOut.Play();
       while (waveOut.PlaybackState == NAudio.Wave.PlaybackState.Playing) {
          System.Threading.Thread.Sleep(100);
       }
    }
    

    【讨论】:

    • +1 有一些注意事项:不需要带有最新 NAudio 的 wavStream 和 baStream。此外,不要使用函数回调,而是使用 WaveOutEvent 类(或者如果您在 WinForms 中,则只需使用常规 WaveOut 构造函数)。睡到文件完成不是我这样做的方式,但它会很有效。
    【解决方案3】:

    您可以通过将任何类型的文件添加到您的资源中来将其嵌入到您的项目中。

    在 Visual Studio 中,您可以通过资源 --> 添加资源 --> 添加现有文件来做到这一点。

    在我的例子中,我将资源文件命名为 mySound。

    然后您可以通过添加以资源为参数的SoundPlayer 来打开文件。

    例如

        SoundPlayer mysoundplayer = new SoundPlayer(MyAssemblyName.Properties.Resources.mySound);
        mysoundplayer.Play();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多