【问题标题】:Naudio generated audio wave form doesn't match the sound for some .wav file and .m4a fileNaudio 生成的音频波形与某些 .wav 文件和 .m4a 文件的声音不匹配
【发布时间】:2021-09-24 21:12:44
【问题描述】:

我尝试开发一种音频字幕工具并使用 Naudio 生成波形供用户识别声音,每个音频大约 1 小时,我发现某些音频的波形与中间的声音不匹配音频。

这里是代码

public static class WaveFormRendererTool
    {
        public static void draw(int width, string filename)
        {
            string imagepath = filename+".png";
            var maxPeakProvider = new MaxPeakProvider();
            var rmsPeakProvider = new RmsPeakProvider(200); // e.g. 200
            var samplingPeakProvider = new SamplingPeakProvider(200); // e.g. 200
            var averagePeakProvider = new AveragePeakProvider(4); // e.g. 4

            SolidBrush brush = new SolidBrush(Color.Green);

            var myRendererSettings = new StandardWaveFormRendererSettings();
            //var myRendererSettings = new SoundCloudBlockWaveFormSettings(Color.Red,Color.Green,Color.Yellow,Color.Blue);
            myRendererSettings.Width = width;
            myRendererSettings.TopHeight = 75;
            myRendererSettings.BottomHeight = 75;
            myRendererSettings.BackgroundColor = Color.White;
            myRendererSettings.PixelsPerPeak = 1;
            myRendererSettings.TopPeakPen = new Pen(brush);
            myRendererSettings.BottomPeakPen = new Pen(brush);
            myRendererSettings.TopSpacerPen = new Pen(brush);
            



            
            var renderer = new WaveFormRenderer();
            var audioFilePath = filename;
            var image = renderer.Render(audioFilePath, averagePeakProvider, myRendererSettings);
           /* if (File.Exists(imagepath)) {
                File.Delete(imagepath);
            }*/
            image.Save(imagepath, ImageFormat.Png);
            renderer=null;
        }

the wave form is flat but already speak

这里是宽度的代码:


                MediaFoundationReader wf = new MediaFoundationReader(file.FullName);
                audioLength = wf.TotalTime.TotalSeconds;
                int width = Convert.ToInt32(wf.TotalTime.TotalSeconds*10);
                
                canvas.Width = width * canstf.ScaleX;
                canvaswidth = canvas.Width;
                canvas.Height = 150;
                img.Width = width;
                //img.Height = 100;
                //img.Height = 100

                img.Source = null;
                WaveFormRendererTool.draw(width, file.FullName);
                img.Source = ImageRotation.LoadImageFile(file.FullName + ".png");
                scroller1.ScrollToHorizontalOffset(0);
                initialCanvas(width);

【问题讨论】:

标签: c# naudio waveform


【解决方案1】:

如果无法访问您的特定源文件,我们将无法重现您的问题,尤其是因为我不知道 width 有什么价值,所以这将是一些猜测。根据音频文件,假设您使用的是 Mark 的 NAudio.WaveFormRenderer 代码,这可能是完全准确的。

说实话,从代码和拉伸的图像来看,我不确定您是否已将图像与时间戳正确同步。如果您在初始化 4 个不同的 PeakProvider 变体时获得了相似的结果,那么几乎可以肯定您的缩放有问题。

很遗憾,您没有提供实际的显示代码,所以我无法指出错误可能出在哪里。您需要返回并交叉检查将时间映射到渲染波形图像宽度的代码。


我在周末使用了该文件,我有理由确定主要问题是您的计算与 WaveFormRenderer 类所做的计算之间存在脱节,这会导致长时间漂移。

WaveFormRenderer 使用Here's the code 来确定每个柱将使用多少个样本:

int bytesPerSample = (reader.WaveFormat.BitsPerSample / 8);
var samples = reader.Length / (bytesPerSample);
var samplesPerPixel = (int)(samples / settings.Width);
var stepSize = settings.PixelsPerPeak + settings.SpacerPixels;
peakProvider.Init(reader, samplesPerPixel * stepSize);

使用您的代码调用它,samplesPerPixel 将截断为 1599 - 1/10 秒内样本数的一小部分。因此,不是在渲染图像中获得每像素 0.1 秒,而是每像素获得 0.0999375 秒。在文件中的 00:24:14(您的屏幕截图所在的位置)累积的漂移约为 0.91 秒。

幸运的是,解决方法很简单,如果对所有关于舍入误差等的讨论有点违反直觉:在计算宽度时使用截断而不是舍入:

int width = (int)(wf.TotalTime.TotalSeconds*10);

这应该保证samplesPerPixel 的计算结果将始终为 1600 而不是 1599,从而使您可以同步播放而不会出现漂移。这肯定比尝试重新调整代码中的所有内容以适应非常轻微的每像素漂移要简单。

【讨论】:

  • 非常感谢您的帮助。我编辑了问题并添加了宽度代码:我使用 MediaFoundationReader 获得了音频长度,然后是 *10。此外,我在屏幕截图中的画布中缩小了 5 倍。奇怪的是对于某些音频它运行良好。顺便说一句,不同的 PeakProvider 会影响不同音频类型的渲染精度吗?
  • @stonelee 好的,你的定位代码肯定有问题。尽可能使用浮点数(或双精度数),否则会出现舍入错误。另请注意,许多 WinForms 定位使用带符号的短整数,所以任何超过 short.MaxValue (32767) 的东西都会换行。
  • 感谢您的跟进。是的,我在 canavs 位置使用 double 。唯一一个带有 int 的宽度是因为 myRendererSettings.Width 只接受 int。此外,一些音频文件运行良好,但对于那些出错的,它与长度的中间不匹配。
  • 您确实帮助找到了根本原因并挽救了我的生命。为你点赞!
猜你喜欢
  • 1970-01-01
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
相关资源
最近更新 更多