Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在WP8上拆分wav文件?_C#_Windows Phone 8_Split_Wav - Fatal编程技术网

C# 如何在WP8上拆分wav文件?

C# 如何在WP8上拆分wav文件?,c#,windows-phone-8,split,wav,C#,Windows Phone 8,Split,Wav,有没有办法在C#WP8中分割wav文件?我想保存一个wav文件的示例,例如,从00:30开始,到00:40结束 可能使用某种流或缓冲区,但我必须知道何时开始/完成将流复制到另一个wav文件 我怎样才能做到这一点呢?在我的博客上,我发布了关于这一点的文章,从这篇关于阅读wave文件的文章()开始,接下来的两篇文章都是基于这一点。。希望有帮助! 最好的 Oliver由于wav文件的头可以从44(标准)到100多个字节不等,因此在开始分割wav文件之前,您需要首先确定头的确切大小,并读取重要的元信息

有没有办法在C#WP8中分割wav文件?我想保存一个wav文件的示例,例如,从00:30开始,到00:40结束

可能使用某种流或缓冲区,但我必须知道何时开始/完成将流复制到另一个wav文件


我怎样才能做到这一点呢?

在我的博客上,我发布了关于这一点的文章,从这篇关于阅读wave文件的文章()开始,接下来的两篇文章都是基于这一点。。希望有帮助! 最好的
Oliver

由于wav文件的头可以从44(标准)到100多个字节不等,因此在开始分割wav文件之前,您需要首先确定头的确切大小,并读取重要的元信息

因此,您需要了解有关wav文件的以下元数据

  • 采样率
  • 钻头深度
  • 频道计数
  • 音频数据格式(样本是PCM还是浮点)
  • 标题大小
在继续之前,我建议您阅读第一篇文章,以便更好地了解代码的作用

所以首先我们需要得到我们的元信息

private void ReadMetaData(FileStream stream, out bool isFloatinfPoint, out int channelCount, out int sampleRate, out int bitDepth, out int headerSize)
{
    var headerBytes = new byte[200];

    // Read header bytes.
    stream.Position = 0;
    stream.Read(headerBytes, 0, 200);

    headerSize = new string(Encoding.ASCII.GetChars(headerBytes)).IndexOf("data") + 8;
    isFloatinfPoint = BitConverter.ToUInt16(new byte[] { headerBytes[20], headerBytes[21] }, 0) == 3 ? true : false;
    channelCount = BitConverter.ToUInt16(new byte[] { headerBytes[22] , headerBytes[23] }, 0);
    sampleRate = (int)BitConverter.ToUInt32(new byte[] { headerBytes[24], headerBytes[25], headerBytes[26], headerBytes[27] }, 0);
    bitDepth = BitConverter.ToUInt16(new byte[] { headerBytes[34], headerBytes[35] }, 0);
}
一旦我们有了这些数据,我们就可以计算我们需要从哪里开始和停止读取我们的文件。要计算开始索引和结束索引

var startIndex = (int)(start.TotalSeconds * sampleRate * byteDepth * channelCount);
var endIndex = (int)(end.TotalSeconds * sampleRate * byteDepth * channelCount);
start
&
end
将是一个
TimeSpan
指示何时开始和停止裁剪

现在,我们可以使用新计算的信息从文件中读取字节,如果您使用的是
FileStream
,您可以执行以下操作:

var newBytes = new byte[endIndex - startIndex];

myStream.Position = headerSize + startIndex; // Add headerSize to position to make sure we don't read the header.
myStream.Read(newBytes, 0, newBytes.Length);
您所要做的就是将wav头与新提取的音频一起写入目标文件。所以,把这些放在一起,你应该得到这样的结果

private void CropWavFile(string inputFilePath, string outputFilePath, TimeSpan start, TimeSpan end)
{
    var stream = new FileStream(inputFilePath, FileMode.Open);
    var newStream = new FileStream(outputFilePath, FileMode.OpenOrCreate);
    var isFloatingPoint = false;
    var sampleRate = 0;
    var bitDepth = 0;
    var channelCount = 0;
    var headerSize = 0;

    // Get meta info
    ReadMetaData(stream, out isFloatingPoint, out channelCount, out sampleRate, out bitDepth, out headerSize);

    // Calculate where we need to start and stop reading.
    var startIndex = (int)(start.TotalSeconds * sampleRate * (bitDepth / 8) * channelCount);
    var endIndex = (int)(end.TotalSeconds * sampleRate * (bitDepth / 8) * channelCount);
    var bytesCount = endIndex - startIndex;
    var newBytes = new byte[bytesCount];

    // Read audio data.
    stream.Position = startIndex + headerSize;
    stream.Read(newBytes, 0, bytesCount);

    // Write the wav header and our newly extracted audio to the new wav file.
    WriteMetaData(newStream, isFloatingPoint, (ushort)channelCount, (ushort)bitDepth, sampleRate, newBytes.Length / (bitDepth / 8));
    newStream.Write(newBytes, 0, newBytes.Length);

    stream.Dispose();
    newStream.Dispose();
}

private void WriteMetaData(FileStream stream, bool isFloatingPoint, ushort channels, ushort bitDepth, int sampleRate, int totalSampleCount)
{
    stream.Position = 0;

    // RIFF header.
    // Chunk ID.
    stream.Write(Encoding.ASCII.GetBytes("RIFF"), 0, 4);

    // Chunk size.
    stream.Write(BitConverter.GetBytes(((bitDepth / 8) * totalSampleCount) + 36), 0, 4);

    // Format.
    stream.Write(Encoding.ASCII.GetBytes("WAVE"), 0, 4);



    // Sub-chunk 1.
    // Sub-chunk 1 ID.
    stream.Write(Encoding.ASCII.GetBytes("fmt "), 0, 4);

    // Sub-chunk 1 size.
    stream.Write(BitConverter.GetBytes(16), 0, 4);

    // Audio format (floating point (3) or PCM (1)). Any other format indicates compression.
    stream.Write(BitConverter.GetBytes((ushort)(isFloatingPoint ? 3 : 1)), 0, 2);

    // Channels.
    stream.Write(BitConverter.GetBytes(channels), 0, 2);

    // Sample rate.
    stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

    // Bytes rate.
    stream.Write(BitConverter.GetBytes(sampleRate * channels * (bitDepth / 8)), 0, 4);

    // Block align.
    stream.Write(BitConverter.GetBytes((ushort)channels * (bitDepth / 8)), 0, 2);

    // Bits per sample.
    stream.Write(BitConverter.GetBytes(bitDepth), 0, 2);



    // Sub-chunk 2.
    // Sub-chunk 2 ID.
    stream.Write(Encoding.ASCII.GetBytes("data"), 0, 4);

    // Sub-chunk 2 size.
    stream.Write(BitConverter.GetBytes((bitDepth / 8) * totalSampleCount), 0, 4);
}

private void ReadMetaData(FileStream stream, out bool isFloatinfPoint, out int channelCount, out int sampleRate, out int bitDepth, out int headerSize)
{
    var headerBytes = new byte[200];

    // Read header bytes.
    stream.Position = 0;
    stream.Read(headerBytes, 0, 200);

    headerSize = new string(Encoding.ASCII.GetChars(headerBytes)).IndexOf("data") + 8;
    isFloatinfPoint = BitConverter.ToUInt16(new byte[] { headerBytes[20], headerBytes[21] }, 0) == 3 ? true : false;
    channelCount = BitConverter.ToUInt16(new byte[] { headerBytes[22] , headerBytes[23] }, 0);
    sampleRate = (int)BitConverter.ToUInt32(new byte[] { headerBytes[24], headerBytes[25], headerBytes[26], headerBytes[27] }, 0);
    bitDepth = BitConverter.ToUInt16(new byte[] { headerBytes[34], headerBytes[35] }, 0);
}

你是怎么读文件的?NAudio还是什么?(或者你还没有到这一步吗?)我发现了一个例子,使用XOdioO2和C++,但它只是让我选择玩/暂停。我将尝试将其与Oliver的示例代码合并。好吧,如果您感兴趣,我将建议您创建自己的实现?这真的很简单。嗯,我可以使用一个示例代码在裁剪之前播放音频示例,只是为了确认。你能帮忙吗?是的,我能,我已经为阅读大量格式的Wav文件上了课,所以裁剪就是简单地从X到Y选择样本。如果你仍然感兴趣,我会发布一个答案。谢谢,这是一个多么好的帖子!我会试试你的代码。这需要一段时间,因为我会尝试与XOdioO2、C++、DirectX集成,我不是那么专家…但我会在完成后报告:)我有机会测试您的代码,它也可以工作。谢谢,现在简单多了。它只是工作:)谢谢你。现在我只需要找出一种方法,从手机上收集的mp3中创建这些WAV,但那是另一回事了。@user2962761所以你需要将mp3转换成WAV?如果是,您是否尝试过使用?是的,这是一个很好的项目,但当我尝试通过nuget添加引用时,出现了一个错误:“无法安装程序包'NAudio 1.7.1'。您正试图将此软件包安装到目标为“WindowsPhone,Version=v8.0”的项目中,但该软件包不包含任何与该框架兼容的程序集引用或内容文件。有关详细信息,请与软件包作者联系。“@user2962761那么为什么不直接打开dll并手动添加对它的引用?我不能因为“无法将对更高版本或不兼容程序集的引用添加到项目中”