NAudio BufferedWaveProvider Buffer持续时间限制导致读取在一定时间后停止



我有一个文本到语音引擎,可以读取考试问题。阅读器似乎工作正常,但是当有大文本需要连续阅读时,我发现了一个问题。

12分钟后(每次(,阅读器停止阅读。我追踪到这与诺迪奥BufferedWaveProviderBufferDuration有关。这是我的代码:

Shared waveOut As WaveOut
Shared waveFormat As WaveFormat
Shared provider As BufferedWaveProvider
Private Shared Function InitializeAudio(Freq As Integer) As Boolean
Try
bNoAudioDected = False
waveOut = New WaveOut()
waveFormat = New WaveFormat(Freq, 16, 1)

provider = New BufferedWaveProvider(waveFormat)
provider.BufferLength = 31457280
''this was added for temporary duration fix
Dim ts = New TimeSpan(0, 30, 0)
provider.BufferDuration = ts
'''''''''''''''''''''''''''''''''''''''''''

provider.DiscardOnBufferOverflow = True
Try
waveOut.Init(provider)
Catch mmEx As NAudio.MmException
ErrorMessage("Audio device not detected!" & vbNewLine & "Please connect an audio device to use the Text-To-Speech system!")
bNoAudioDected = True
bAudioInitialised = True
Return False
Catch ex As Exception
WriteError(ex, "TextToSpeech -> InitializeAudio")
bNoAudioDected = True
bAudioInitialised = True
Return False
End Try
Return True
Catch ex As Exception
End Try
End Function
Private Shared Sub ReleaseAudio()
Try
If provider IsNot Nothing Then
provider.ClearBuffer()
End If
If waveOut IsNot Nothing Then
waveOut.[Stop]()
End If
Catch ex As Exception
End Try
End Sub

我注意到默认BufferDuration设置为:11:53 分钟。我在代码中使用TimeSpan将其更改为 10 秒。10 秒后,系统执行的操作与 12 分钟问题完全相同。

此后,我根据上面的代码手动更改了持续时间,首先更改为 6 小时(只是为了过度补偿(,这会导致系统立即爆炸。然后到 2 小时,这似乎工作正常,但会导致较小的文本选择问题。然后到 30 分钟,它现在是什么,这似乎是稳定的,但我担心可靠性,因为我的其他两次尝试似乎引起了更多问题。

我的问题基本上是,这是否是对 NAudio 的 dll 的限制,它只能处理那么多的连续阅读?

缓冲区持续时间应该像我当前所做的那样更改还是默认值应该保持不变?

编辑

这是我使用的文本到语音转换包装器类。请注意,这是由我使用的文本转语音提供程序提供的。

Imports NAudio.Wave
Imports VENET
Imports System.Threading.Thread
Public Class TextToSpeech
#Region "Variables"
#Region "Shared"
Shared sText As String
Shared sDir As String()
Public Shared iSpeechRate As Integer = 100
Shared hTtsInstance As IntPtr
Shared hTtsCl As IntPtr
Public Shared bUploadTypePaper As Boolean = False
#End Region
#Region "Global"
Dim lstText As List(Of String)
Dim nErr As NUAN_ERROR
Dim tts As New VETts
Dim Lang As VE_LANGUAGE()
Dim Voice As VE_VOICEINFO()
Dim thread As Threading.Thread
#End Region
#End Region
#Region "Properties"
Private _newSpeed As Integer
Public Property NewSpeed() As Integer
Get
Return _newSpeed
End Get
Set(ByVal value As Integer)
_newSpeed = value
End Set
End Property
#End Region
Private SpeechHandler As New VENET.VE_OUTPUTDEVICE(AddressOf StreamSpeech)
Private Function StreamSpeech(hTtsInst As IntPtr, Msg As VE_MSG, Param As VE_LPARAM, OutData As VE_OUTDATA) As NUAN_ERROR
Try
If OutData.pOutPcmBuf IsNot Nothing Then
provider.AddSamples(OutData.pOutPcmBuf, 0, CInt(OutData.ulPcmBufLen))
End If
Catch ex As Exception
MessageBox.Show("StreamSpeech FAILED: " & nErr)
MessageBox.Show("StreamSpeech FAILED: " & ex.InnerException.ToString())
End Try
Return NUAN_ERROR.NUAN_OK

End Function

Private Sub ExecuteTts()
Try
NewSpeed = TtsSpeechSpeed
nErr = tts.ve_ttsGetLanguageList(hTtsCl, Lang)
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsGetLanguageList FAILED: " & nErr)
Exit Sub
End If
If Lang.Length = 0 Then
MessageBox.Show("There are no available languages!")
Exit Sub
End If
nErr = tts.ve_ttsGetVoiceList(hTtsCl, Lang(iLang).szLanguage, 0, Voice)
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsGetVoiceList FAILED: " & nErr)
Exit Sub
End If
If Voice.Length = 0 Then
MessageBox.Show("There are no available voices!")
Exit Sub
End If
Dim paramList() As VE_PARAM
paramList = New VE_PARAM() {New VE_PARAM(VE_PARAMID.VE_PARAM_LANGUAGE, Lang(iLang).szLanguage), New VE_PARAM(VE_PARAMID.VE_PARAM_SPEECHRATE), New VE_PARAM(VE_PARAMID.VE_PARAM_VOICE, Voice(iVoice).szVoiceName)}
If NewSpeed <> 0 Then
iSpeechRate = NewSpeed
ElseIf NewSpeed = 0 Then
paramList(1).usValue = iSpeechRate
End If
paramList(1).usValue = iSpeechRate
Try
nErr = tts.ve_ttsSetParamList(hTtsInstance, paramList)
Catch ex As Exception
MsgBox(ex.Message)
End Try
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsSetParamList FAILED: " & nErr)
Exit Sub
End If
Dim FreqParam As VE_PARAM() = {New VE_PARAM(VE_PARAMID.VE_PARAM_FREQUENCY)}
nErr = tts.ve_ttsGetParamList(hTtsInstance, FreqParam)
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsGetParamList FAILED: " & nErr)
Exit Sub
End If
tts.tts_setOutDevice(SpeechHandler)
' Start Streaming Audio
Try
waveOut.Play()
Catch ex As Exception
End Try

nErr = tts.ve_ttsProcessText2Speech(hTtsInstance, VE_TEXTFORMAT.VE_NORM_TEXT, sText)
If nErr <> NUAN_ERROR.NUAN_OK And nErr <> NUAN_ERROR.NUAN_E_TTS_USERSTOP Then
MessageBox.Show("ve_ttsProcessText2Speech FAILED: " & nErr)
Exit Sub
End If
Catch ex As Exception
MessageBox.Show("ExecuteTts FAILED: " & nErr)
MessageBox.Show("ExecuteTts FAILED: " & ex.Message.ToString())
MessageBox.Show("ExecuteTts FAILED: " & ex.InnerException.ToString())
End Try
End Sub

Public Function InitialiseTtsEngine() As Boolean
Try

sDir = {sTtsEnginePath}
nErr = tts.ve_ttsInitialize(sDir, hTtsCl)
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsInitialize FAILED: " & nErr)
Exit Function
End If
nErr = tts.ve_ttsOpen(hTtsCl, hTtsInstance)
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsOpen FAILED: " & nErr)
Exit Function
End If
If Not InitializeAudio(22050) Then
MessageBox.Show("Could not initialize audio with sampling frequency")
End If
Catch ex As Exception
End Try
End Function
Public Sub CleanUp()
If hTtsInstance <> 0 Then
nErr = tts.ve_ttsStop(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsStop FAILED: " & nErr)
Exit Sub
End If
Sleep(1500)
nErr = tts.ve_ttsClose(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsClose FAILED: " & nErr)
Exit Sub
End If
End If
End Sub
Public Function UnInitialiseTtsEngineForTest() As Boolean
Try
If hTtsInstance <> 0 Then
nErr = tts.ve_ttsStop(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsStop FAILED: " & nErr)
End If
Sleep(1500)
nErr = tts.ve_ttsClose(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsClose FAILED: " & nErr)
Exit Function
End If
nErr = tts.ve_ttsUnInitialize(hTtsCl)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsUnInitialize FAILED: " & nErr)
Exit Function
End If
ReleaseAudio()
GC.Collect()
End If
Catch ex As Exception
End Try
End Function
Public Function UnInitialiseTtsEngineForQTCTest() As Boolean
Try
If hTtsInstance <> 0 Then
nErr = tts.ve_ttsStop(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsStop FAILED: " & nErr)
End If
nErr = tts.ve_ttsClose(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsClose FAILED: " & nErr)
Exit Function
End If
nErr = tts.ve_ttsUnInitialize(hTtsCl)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsUnInitialize FAILED: " & nErr)
Exit Function
End If
ReleaseAudio()
GC.Collect()
End If
Catch ex As Exception
End Try
End Function
Public Function UnInitialiseTtsEngine() As Boolean
Try
If hTtsInstance <> 0 Then
nErr = tts.ve_ttsClose(hTtsInstance)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsClose FAILED: " & nErr)
Exit Function
End If
nErr = tts.ve_ttsUnInitialize(hTtsCl)
Application.DoEvents()
If nErr <> NUAN_ERROR.NUAN_OK Then
MessageBox.Show("ve_ttsUnInitialize FAILED: " & nErr)
Exit Function
End If
ReleaseAudio()
GC.Collect()
End If
Catch ex As Exception
End Try
End Function
Public Sub PlayTts(ByVal text As String)
Try
sText = text
If thread IsNot Nothing Then
tts.ve_ttsStop(hTtsInstance)
ReleaseAudio()
thread.Join()
thread = Nothing
End If
thread = New Threading.Thread(AddressOf ExecuteTts)
thread.Start()
Catch ex As Exception

End Try
End Sub
Public Sub PauseResumeTts()
Try
If waveOut.PlaybackState = PlaybackState.Playing Then
waveOut.Pause()
ElseIf waveOut.PlaybackState = PlaybackState.Paused Then
waveOut.Resume()
End If
Catch ex As Exception
WriteError(ex, "TextToSpeech -> PlayPauseTts")
End Try
End Sub
Shared waveOut As WaveOut
Shared waveFormat As WaveFormat
Shared provider As BufferedWaveProvider
Private Shared Function InitializeAudio(Freq As Integer) As Boolean
If bUploadTypePaper = True Then

Try
bNoAudioDected = False
waveOut = New WaveOut()
waveFormat = New WaveFormat(Freq, 16, 1)

provider = New BufferedWaveProvider(waveFormat)
provider.BufferLength = 31457280
Dim ts = New TimeSpan(0, 30, 0)
provider.BufferDuration = ts
provider.DiscardOnBufferOverflow = True
Try
waveOut.Init(provider)
Catch mmEx As NAudio.MmException
ErrorMessage("Audio device not detected!" & vbNewLine & "Please connect an audio device to use the Text-To-Speech system!")
bNoAudioDected = True
bAudioInitialised = True
Return False
Catch ex As Exception
WriteError(ex, "TextToSpeech -> InitializeAudio")
bNoAudioDected = True
bAudioInitialised = True
Return False
End Try
Return True
Catch ex As Exception
End Try
End If

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''This was provided
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Try
bNoAudioDected = False
waveOut = New WaveOut()
waveFormat = New WaveFormat(Freq, 16, 1)

provider = New BufferedWaveProvider(waveFormat)
provider.BufferLength = 31457280
provider.DiscardOnBufferOverflow = True
Try
waveOut.Init(provider)
Catch mmEx As NAudio.MmException
ErrorMessage("Audio device not detected!" & vbNewLine & "Please connect an audio device to use the Text-To-Speech system!")
bNoAudioDected = True
bAudioInitialised = True
Return False
Catch ex As Exception
WriteError(ex, "TextToSpeech -> InitializeAudio")
bNoAudioDected = True
bAudioInitialised = True
Return False
End Try
Return True
Catch ex As Exception
End Try
End Function
Private Shared Sub ReleaseAudio()
Try
If provider IsNot Nothing Then
provider.ClearBuffer()
End If
If waveOut IsNot Nothing Then
waveOut.[Stop]()
End If
Catch ex As Exception
End Try
End Sub
End Class

这是我单击"阅读文本"按钮时使用的代码:

If CStr(currentSelection.type) <> "None" Then
Dim range As IHTMLTxtRange = TryCast(currentSelection.createRange(), IHTMLTxtRange)
If IsNothing(range.text) Then
MessageBox.Show("There is no available text to be read!", "No Text Available", MessageBoxButtons.OK, MessageBoxIcon.Hand)
Exit Sub
End If
If range IsNot Nothing Then
CallTts(range.text)
End If
ElseIf currentSelection Is Nothing And String.IsNullOrEmpty(browserContents) Then
MessageBox.Show("There is no available text to be read!", "No Text Available", MessageBoxButtons.OK, MessageBoxIcon.Hand)
Exit Sub
Else
CallTts(browserContents)
End If

最后,CallTts函数代码,然后转到TextToSpeech类,提供了:

Try
If thread IsNot Nothing Then
tts.ve_ttsStop(hTtsInstance)
ReleaseAudio()
thread.Join()
thread = Nothing
End If
thread = New Threading.Thread(AddressOf ExecuteTts)
thread.Start()
Catch ex As Exception
End Try

BufferedWaveProvider背后的整个想法是一个线程正在填充它,而另一个线程正在从中读取。填充和读取的速率需要大致相同,否则填充线程将溢出缓冲区或读取线程将出现丢失。如果您尝试将缓冲区的大小设置为几个小时,听起来您的用例根本不适合BufferedWaveProvider。如何将音频添加到BufferedWaveProvider

相关内容

  • 没有找到相关文章

最新更新