繁体   English   中英

Naudio 生成的音频波形与某些 .wav 文件和 .m4a 文件的声音不匹配

[英]Naudio generated audio wave form doesn't match the sound for some .wav file and .m4a file

我尝试开发一个用于音频字幕的工具,并使用 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;
        }

波形是平坦的,但已经说话了

这是宽度的代码:


                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);

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

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

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


我在周末玩了这个文件,我有理由确定主要问题是您的计算与WaveFormRenderer类完成的计算之间存在脱节,这导致了长时间的漂移。

以下是WaveFormRenderer用于确定每个柱将使用多少样本的代码

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,从而允许您同步播放而不会出现漂移。 这肯定比尝试重新调整代码中的所有内容以适应非常轻微的每像素漂移更简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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