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

时间:2016-02-11 09:25:13

标签: c# audio wav audio-recording naudio

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

录制和复制应该并行进行。 我已经实施了一项预定作业,该作业将每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的{​​{1}}
  3. 从位置开始读取源文件直到结束。

    waveReader
  4. 我能够获得新内容。

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

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

    我的代码抛出以下异常 - 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(); } } }

2 个答案:

答案 0 :(得分:3)

我无法找到使用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);
        }
    }
    

答案 1 :(得分:0)

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

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