修剪一个wav文件

3

我正在尝试使用这里的代码来裁剪文件。

 public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd)
 {
    using (WaveFileReader reader = new WaveFileReader(inPath))
    {
        using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))
        {
            int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;

            int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;
            startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

            int endBytes = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;
            endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
            int endPos = (int)reader.Length - endBytes; 

            TrimWavFile(reader, writer, startPos, endPos);
        }
    }
}

private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)
{
    reader.Position = startPos;
    byte[] buffer = new byte[1024];
    while (reader.Position < endPos)
    {
        int bytesRequired = (int)(endPos - reader.Position);
        if (bytesRequired > 0)
        {
            int bytesToRead = Math.Min(bytesRequired, buffer.Length);
            int bytesRead = reader.Read(buffer, 0, bytesToRead);
            if (bytesRead > 0)
            {
                writer.WriteData(buffer, 0, bytesRead);
            }
        }
    }
}

我按照文件中的内容进行了编写,但是当我打开修剪后的文件时,它显示已损坏。

这段代码是怎样工作的呢?while (reader.Position < endPos)始终为真,而reader.Position没有变化。

编辑1 else if()与else相同,只是为了确保而已。

while (reader.Position < end)
        {
            int bytesRequired = (int)(end - reader.Position);
            if (bytesRequired > 0)
            {
                int bytesToRead = Math.Min(bytesRequired, buffer.Length);
                int bytesRead = reader.Read(buffer, 0, bytesToRead);
                if (bytesRead > 0)
                {
                    writer.Write(buffer, 0, bytesRead);
                }
                else if (bytesRead == 0)
                {
                   break;
                }
            }
            else if (bytesRequired <= 0)
            {
                break;
            }
        }
3个回答

1
如果bytesRequired <= 0或者bytesRead == 0,你应该跳出while循环。

我已经这样做了,但仍然得到这个错误:https://i.stack.imgur.com/wDT0S.png 你有任何想法为什么会这样吗? - EldarGoren
输入文件能否播放?Waveformat是什么? - Mark Heath
输入是可播放的并且是一个wav文件。 - EldarGoren
我调试了程序,它甚至没有进入else并且打破了while循环。我在问题中添加了代码。 - EldarGoren

0
我找到了解决方案。完成后,我必须编写 writer.Dispose()。像这样:

public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd)
 {
    using (WaveFileReader reader = new WaveFileReader(inPath))
    {
        using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))
        {
            int bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000;

            int startPos = (int)cutFromStart.TotalMilliseconds * bytesPerMillisecond;
            startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

            int endBytes = (int)cutFromEnd.TotalMilliseconds * bytesPerMillisecond;
            endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
            int endPos = (int)reader.Length - endBytes; 

            TrimWavFile(reader, writer, startPos, endPos);
            writer.Dispose();
        }
    }

2
奇怪 - 这就是 using 语句应该为您完成的工作。 - Mark Heath

0

你使用的示例代码有点过时并且存在一些错误。

这里是一个更新后的版本(对我来说完美地工作):

private void Cut()
{
  var filename = @"G:\Voice\Samples\LongAudioFile.wav";
  FileInfo fi = new FileInfo(filename);
  var outputPath = System.IO.Path.Combine(fi.Directory.FullName, string.Format("{0}_Shorter{1}", fi.Name.Replace(fi.Extension, ""), fi.Extension));

  TrimWavFile(filename, outputPath, TimeSpan.FromHours(1));
}

public static void TrimWavFile(string inPath, string outPath, TimeSpan duration)
{
  using (WaveFileReader reader = new WaveFileReader(inPath))
  {
    using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))
    {
      float bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000f;

      int startPos = 0;
      startPos = startPos - startPos % reader.WaveFormat.BlockAlign;

      int endBytes = (int)Math.Round(duration.TotalMilliseconds * bytesPerMillisecond);
      endBytes = endBytes - endBytes % reader.WaveFormat.BlockAlign;
      int endPos = endBytes;

      TrimWavFile(reader, writer, startPos, endBytes);
    }
  }
}

private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)
{
  reader.Position = startPos;
  byte[] buffer = new byte[reader.BlockAlign * 1024];
  while (reader.Position < endPos)
  {
    int bytesRequired = (int)(endPos - reader.Position);
    if (bytesRequired > 0)
    {
      int bytesToRead = Math.Min(bytesRequired, buffer.Length);
      int bytesRead = reader.Read(buffer, 0, bytesToRead);
      if (bytesRead > 0)
      {
        writer.Write(buffer, 0, bytesRead);
      }
    }
  }
}

请注意,在我的情况下,我需要从启动开始获取音频到某个特定点(例如:1小时)。如果您想在中间获取特定部分,请更改:
int startPos = 0;

int startBytes = (int)Math.Round(startPoint.TotalMilliseconds * bytesPerMillisecond);
startBytes = startBytes - startBytes % reader.WaveFormat.BlockAlign;
int startPos = startBytes;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接