[英]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.