【问题标题】:C# sound visualisation [closed]C# 声音可视化 [关闭]
【发布时间】:2010-11-24 04:55:25
【问题描述】:

我想使用 C# 语言和 .NET Framework 创建一个完善的可视化系统。 这可能看起来像在 Winamp 应用程序中。 也许存在免费图书馆或一些描述如何做到这一点的有趣文章? 例子: alt text http://img44.imageshack.us/img44/9982/examplel.png

【问题讨论】:

    标签: c# .net audio bitmap noise


    【解决方案1】:

    你可以试试这些链接

    OpenVP(是一个用于开发音乐可视化的免费开源平台,用 C# 编写),请参阅OpenVP Screenshots

    Sound visualizer in C#

    Play and Visualize WAV Files using Managed Direct Sound

    再见。

    【讨论】:

      【解决方案2】:

      这是一个使用 WASAPI API 计算在计算机上播放的任何声音的 FFT 的脚本。它使用 CSCore 及其WinformsVisualization 示例:

      using CSCore;
      using CSCore.SoundIn;
      using CSCore.Codecs.WAV;
      using WinformsVisualization.Visualization;
      using CSCore.DSP;
      using CSCore.Streams;
      using System;
      
      public class SoundCapture
      {
      
          public int numBars = 30;
      
          public int minFreq = 5;
          public int maxFreq = 4500;
          public int barSpacing = 0;
          public bool logScale = true;
          public bool isAverage = false;
      
          public float highScaleAverage = 2.0f;
          public float highScaleNotAverage = 3.0f;
      
      
      
          LineSpectrum lineSpectrum;
      
          WasapiCapture capture;
          WaveWriter writer;
          FftSize fftSize;
          float[] fftBuffer;
      
          SingleBlockNotificationStream notificationSource;
      
          BasicSpectrumProvider spectrumProvider;
      
          IWaveSource finalSource;
      
          public SoundCapture()
          {
      
              // This uses the wasapi api to get any sound data played by the computer
              capture = new WasapiLoopbackCapture();
      
              capture.Initialize();
      
              // Get our capture as a source
              IWaveSource source = new SoundInSource(capture);
      
      
              // From https://github.com/filoe/cscore/blob/master/Samples/WinformsVisualization/Form1.cs
      
              // This is the typical size, you can change this for higher detail as needed
              fftSize = FftSize.Fft4096;
      
              // Actual fft data
              fftBuffer = new float[(int)fftSize];
      
              // These are the actual classes that give you spectrum data
              // The specific vars of lineSpectrum here aren't that important because they can be changed by the user
              spectrumProvider = new BasicSpectrumProvider(capture.WaveFormat.Channels,
                          capture.WaveFormat.SampleRate, fftSize);
      
              lineSpectrum = new LineSpectrum(fftSize)
              {
                  SpectrumProvider = spectrumProvider,
                  UseAverage = true,
                  BarCount = numBars,
                  BarSpacing = 2,
                  IsXLogScale = false,
                  ScalingStrategy = ScalingStrategy.Linear
              };
      
              // Tells us when data is available to send to our spectrum
              var notificationSource = new SingleBlockNotificationStream(source.ToSampleSource());
      
              notificationSource.SingleBlockRead += NotificationSource_SingleBlockRead;
      
              // We use this to request data so it actualy flows through (figuring this out took forever...)
              finalSource = notificationSource.ToWaveSource();
      
              capture.DataAvailable += Capture_DataAvailable;
              capture.Start();
          }
      
          private void Capture_DataAvailable(object sender, DataAvailableEventArgs e)
          {
              finalSource.Read(e.Data, e.Offset, e.ByteCount);
          }
      
          private void NotificationSource_SingleBlockRead(object sender, SingleBlockReadEventArgs e)
          {
              spectrumProvider.Add(e.Left, e.Right);
          }
      
          ~SoundCapture()
          {
              capture.Stop();
              capture.Dispose();
          }
      
          public float[] barData = new float[20];
      
          public float[] GetFFtData()
          {
              lock (barData)
              {
                  lineSpectrum.BarCount = numBars;
                  if (numBars != barData.Length)
                  {
                      barData = new float[numBars];
                  }
              }
      
              if (spectrumProvider.IsNewDataAvailable)
              {
                  lineSpectrum.MinimumFrequency = minFreq;
                  lineSpectrum.MaximumFrequency = maxFreq;
                  lineSpectrum.IsXLogScale = logScale;
                  lineSpectrum.BarSpacing = barSpacing;
                  lineSpectrum.SpectrumProvider.GetFftData(fftBuffer, this);
                  return lineSpectrum.GetSpectrumPoints(100.0f, fftBuffer);
              }
              else
              {
                  return null;
              }
          }
      
          public void ComputeData()
          {
      
      
              float[] resData = GetFFtData();
      
              int numBars = barData.Length;
      
              if (resData == null)
              {
                  return;
              }
      
              lock (barData)
              {
                  for (int i = 0; i < numBars && i < resData.Length; i++)
                  {
                      // Make the data between 0.0 and 1.0
                      barData[i] = resData[i] / 100.0f;
                  }
      
                  for (int i = 0; i < numBars && i < resData.Length; i++)
                  {
                      if (lineSpectrum.UseAverage)
                      {
                          // Scale the data because for some reason bass is always loud and treble is soft
                          barData[i] = barData[i] + highScaleAverage * (float)Math.Sqrt(i / (numBars + 0.0f)) * barData[i];
                      }
                      else
                      {
                          barData[i] = barData[i] + highScaleNotAverage * (float)Math.Sqrt(i / (numBars + 0.0f)) * barData[i];
                      }
                  }
              }
      
          }
      }
      

      然后,当从不同的脚本中检索 barData 时,建议先锁定它,因为这是在单独的线程上修改的。

      我不确定我从哪里得到GetSpectrumPoints,因为它似乎不在Github Repo 中,但在这里。只需将其粘贴到该文件中,我的代码就可以工作了。

      public float[] GetSpectrumPoints(float height, float[] fftBuffer)
      {
          SpectrumPointData[] dats = CalculateSpectrumPoints(height, fftBuffer);
          float[] res = new float[dats.Length];
          for (int i = 0; i < dats.Length; i++)
          {
              res[i] = (float)dats[i].Value;
          }
      
          return res;
      }
      

      【讨论】:

      • 我尝试使用您的示例代码,但它看起来不像GetSpectrumPoints() is a function anymore,并且检查 git 存储库历史记录也没有显示它。您介意澄清/更新您的答案吗? (我正在尝试将 Windows 上的音频捕获/处理与驱动 LED 灯的跨平台控制台应用程序集成;它只需要 0.0 到 1.0 条频率数据值
      • @Shane 对不起!我现在添加了该代码,希望对您有所帮助
      猜你喜欢
      • 2011-03-10
      • 2014-01-10
      • 2010-12-10
      • 2010-09-14
      • 2010-09-06
      • 1970-01-01
      • 2013-09-19
      • 2012-12-25
      • 1970-01-01
      相关资源
      最近更新 更多