一个波形文件的时间长度

8
我有一些简单的代码,使用TTS生成波形文件并播放它:
public void TestSpeech()
{
    SpeechSynthesizer synth = new SpeechSynthesizer();
    using (MemoryStream stream = new MemoryStream())
    {
        synth.SetOutputToWaveStream(stream);
        synth.Speak("Hello world");
        stream.Seek(0, SeekOrigin.Begin);
        IWaveSource source = new WaveFileReader(stream);
        EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
        var soundOut = new WasapiOut();
        soundOut.Initialize(source);
        soundOut.Stopped += (s, e) => waitHandle.Set();
        soundOut.Play();
        waitHandle.WaitOne();
        soundOut.Dispose();
        source.Dispose();
    }
}

一切都运行良好, 但在播放音频文件之前,我想知道它将持续多长时间。是否有一种计算方法,或者是否可以从某处获取这个信息?

如果可获取,如何计算?我假设它与流中的数据量有关,但具体如何计算呢?


类似的问题已经在这里得到回答:https://dev59.com/cnVD5IYBdhLWcg3wHnwX - Maxim Fleitling
一定会有办法,没有什么是不可能的。这个问题让我着迷。如果我有任何想法,我会发布出来,否则我将带着失败的尾巴黯然离开。 - Gabe
正如链接文章中所述,以前没有一种可靠的方法来实现它,但 Genti 的解决方案是实现结果的好方法。请参阅 Genti 描述的评论以了解长度计算详细信息。 - Gabe
3个回答

7

您可以使用CSCoreNAudio

CSCore(从this sample中提取,当前播放位置和总持续时间在这里被使用):

using System;
using CSCore;
using CSCore.Codecs.WAV;

IWaveSource wavSource = new WaveFileReader(stream);
TimeSpan totalTime = wavSource.GetLength();

NAudio

using System;
using NAudio.Wave;

using (var wfr = new WaveFileReader(stream))
{
    TimeSpan totalTime = wfr.TotalTime;
}

还可以参见TimeSpan的MSDN文档

该持续时间是根据WAVE数据的总长度(对于压缩文件可能是一个估计值)和每秒平均字节数(根据TotalTime属性中的NAudio源代码)计算出来的:

totalTimeInSeconds = LengthInBytes / AverageBytesPerSecond;

他可以访问stream。合成器会向stream写入数据。 - Genti Saliu
1
我在点击“添加”后立即删除了我的评论,因为我意识到我的逻辑错误。很抱歉我的朋友。 - Gabe
谢谢。"持续时间是从WAVE数据的总长度(这可以是压缩文件的估计)和平均每秒字节数计算出来的"。我在哪里可以找到平均每秒字节数?这是使用CSCore。 - user1596371
AverageBtyesPerSecond 是 NAudio 中的一个属性 在这里。根据采样率和长度,这是我目前找到的。只需跟踪源代码返回到定义每个属性的位置,您很快就会找到答案,甚至可以在 VS 中查看定义,速度会更快。 - Gabe
1
在CSCore中,您可以使用wavSource.WaveFormat.BytesPerSecond获取它。 - Genti Saliu
显示剩余2条评论

0

如果有人正在寻找解决方法,我是这样处理的:

  1. 我创建了一个布尔变量mouseScrewsAround = false
  2. 计时器事件,在播放时更改trackBar位置,仅在!mouseScrewsAround时触发
  3. trackBar_MouseDown -> mouseScrewsAround = true
  4. trackBar_MouseUp -> 更改track位置,然后mouseScrewsAround = false

0
using CSCore;

IWaveSource waveSource = new WaveFileReader(stream);
TimeSpan totalTime = waveSource.GetLength( ); //get length returns a timespan

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