繁体   English   中英

使用Naudio复制Wave文件 - 复制/附加最新可用字节

[英]Replicate Wave file using Naudio - Copy/Append Latest Available bytes

我有一个Active wave录制wave-file.wav发生在Source文件夹中。 我需要使用新名称wave-file-copy.wav将此文件复制到Destination文件夹。

录制和复制应该并行进行。 我已经实现了一个预定的作业,它将每10分钟运行一次,并将source文件复制到destination

private static void CopyWaveFile(string destinationFile, string sourceFile){
        using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
            using (var reader = new WaveFileReader(fs)){
                using (var writer = new WaveFileWriter(destinationFile, reader.WaveFormat)){
                    reader.Position = 0;
                    var endPos = (int)reader.Length;
                    var buffer = new byte[1024];
                    while (reader.Position < endPos){
                        var bytesRequired = (int)(endPos - reader.Position);
                        if (bytesRequired <= 0) continue;
                        var bytesToRead = Math.Min(bytesRequired, buffer.Length);
                        var bytesRead = reader.Read(buffer, 0, bytesToRead);
                        if (bytesRead > 0){
                            writer.Write(buffer, 0, bytesRead);
                        }
                    }
                }
            }
        }
    }

即使源文件正在不断更新,复制操作也能正常工作。

复制操作所花费的时间在线性时间内增加,因为我每次都复制整个文件。

我正在尝试实现一个新函数ConcatenateWavFiles() ,它应该使用最新的源记录字节来更新目标文件的内容。

我尝试过几个示例代码 - 我使用的方法是:

  1. 读取目标文件元信息,并获取长度。
  2. 将目标文件的length设置为reader.Position 。源文件waveReader
  3. 从位置开始读取源文件直到结束。

     public static void ConcatenateWavFiles(string destinationFile, string sourceFile){ WaveFileWriter waveFileWriter = null; var sourceReadOffset = GetWaveFileSize(destinationFile); try{ using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var reader = new WaveFileReader(fs)) { waveFileWriter = new WaveFileWriter(destinationFile, reader.WaveFormat); if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat)){ throw new InvalidOperationException( "Can't append WAV Files that don't share the same format"); } var startPos = sourceReadOffset - sourceReadOffset % reader.WaveFormat.BlockAlign; var endPos = (int) reader.Length; reader.Position = startPos; var bytesRequired = (int)(endPos - reader.Position); var buffer = new byte[bytesRequired]; if (bytesRequired > 0) { var bytesToRead = Math.Min(bytesRequired, buffer.Length); var bytesRead = reader.Read(buffer, 0, bytesToRead); if (bytesRead > 0) { waveFileWriter.Write(buffer, startPos, bytesRead); } } } } } finally{ if (waveFileWriter != null){ waveFileWriter.Dispose(); } } } 

我能够获得新内容。

是否可以将最新内容附加到现有目标文件?

如果可能,我在代码中做错了什么?

我的代码抛出以下异常 - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.

我找不到使用NAudio Library进行波形音频文件复制的解决方案。

但我已经使用C#MemoryStreams和FileStreams实现了一个解决方案。

  1. 如果目标文件不存在,则将源文件复制到目标。
  2. 将所有最新字节(在上次操作之后记录)附加到目标文件。
  3. 修改Wave File Header以反映最后添加的字节。 (否则文件的持续时间不会更新,只会增加文件大小。
  4. 定期重复此追加操作。

     public void ReplicateFile(string destinationFile, string sourceFile){ if (!Directory.Exists(GetRoutePathFromFile(sourceFile))) return; if (!File.Exists(sourceFile)) return; if (Directory.Exists(GetRoutePathFromFile(destinationFile))){ if (File.Exists(destinationFile)){ UpdateLatestWaveFileContent(destinationFile, sourceFile); }else{ CopyWaveFile(destinationFile, sourceFile); } }else{ Directory.CreateDirectory(GetRoutePathFromFile(destinationFile)); CopyWaveFile(destinationFile, sourceFile); } } private static string GetRoutePathFromFile(string file){ var rootPath = Directory.GetParent(file); return rootPath.FullName; } private static void CopyWaveFile(string destination, string source){ var sourceMemoryStream = new MemoryStream(); using (var fs = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ fs.CopyTo(sourceMemoryStream); } using (var fs = new FileStream(destination, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite)){ sourceMemoryStream.WriteTo(fs); } } private static void UpdateLatestWaveFileContent(string destinationFile, string sourceFile){ var sourceMemoryStream = new MemoryStream(); long offset = 0; using (var fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ offset = fs.Length; } using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ fs.CopyTo(sourceMemoryStream); } var length = sourceMemoryStream.Length - offset; var buffer = sourceMemoryStream.GetBuffer(); using (var fs = new FileStream(destinationFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)){ fs.Write(buffer, (int)offset, (int)length); } var bytes = new byte[45]; for (var i = 0; i < 45; i++){ bytes[i] = buffer[i]; } ModifyHeaderDataLength(destinationFile, 0, bytes); } private static void ModifyHeaderDataLength(string filename, int position, byte[] data){ using (Stream stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) { stream.Position = position; stream.Write(data, 0, data.Length); } } 

尝试在源文件的实际结束之前读取源文件一个或两个Wav块。

情况可能是代码判断源文件的结尾太近以至于不舒服。

暂无
暂无

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

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