Что нового

не останавливается функция SoundPlay

sasha1304

Новичок
Сообщения
41
Репутация
0
всем привет. пишу программу Синтез речи. столкнулся с проблемой, воспроизведение голоса открывается функцией SoundPlay, после воспроизведения голосовой файл должен удалиться, но этого не происходит потому, что функция SoundPlay($files) продолжает работать и занимать голосовой файл. вариант SoundPlay($files,1) работает,файл освобождается после проигрывания и удаляется. НО, если файл большой и долго читает текст, то тогда в ручную кнопкой "Остановить" его не остановить. т.к скрипт ждёт когда функция SoundPlay завершит свою работу, и только после этого реагирует на действия пользователя. подскажите как быть?

Код:
#include <Encoding.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <ComboConstants.au3>
#NoTrayIcon

Global $files = @ScriptDir & "\sintez.mp3"

GUICreate("Сентизатор речи", 715, 340, -1, -1)
GUICtrlCreateLabel("Введите текст:", 10, 5, 525, 20, $SS_CENTER)
$textedit = GUICtrlCreateEdit("", 10, 25, 525, 305, $WS_VSCROLL + $ES_WANTRETURN)
GUICtrlSetBkColor($textedit, 0x0000A0)
GUICtrlSetColor($textedit, 0xFFFF86)
GUICtrlSetFont($textedit, 12, "", "", "Comic Sans MS")
GUICtrlCreateLabel("Голос: женский/мужской", 545, 25, 160, 20, $SS_LEFT)
$golos_list = GUICtrlCreateCombo("", 545, 45, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($golos_list, "jane|oksana|alyss|omazh|zahar|ermil", "oksana")
GUICtrlCreateLabel("Эмоции голоса", 545, 70, 160, 20, $SS_LEFT)
$emotion_list = GUICtrlCreateCombo("", 545, 90, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($emotion_list , "Доброжелательный|Раздраженный|Нейтральный", "Доброжелательный")
$start = GUICtrlCreateButton("Прочитать", 545, 120, 160, 20)
GUICtrlSetState($start, $GUI_DISABLE)
$stop = GUICtrlCreateButton("Остановить", 545, 150, 160, 20)
GUICtrlSetState($stop, $GUI_DISABLE)

$textvalid = 0
GUISetState(@SW_SHOW)
While  1
	If Not (GUICtrlRead($textedit) == $textvalid) Then
		If GUICtrlRead($textedit) == "" Then
			GUICtrlSetState($start, $GUI_DISABLE)
		Else
			GUICtrlSetState($start, $GUI_ENABLE)
		EndIf
			$textvalid = GUICtrlRead($textedit)
	EndIf
	
	Switch GUIGetMsg()
		Case $start
				ApiSintezYa(GUICtrlRead($textedit), GUICtrlRead($golos_list), GUICtrlRead($emotion_list))
		Case $stop
				_GuiBlock()
		Case $GUI_EVENT_CLOSE

		ExitLoop
	EndSwitch
WEnd

Func ApiSintezYa($text, $golos, $emotion)
	Switch $emotion
		Case "Доброжелательный"
			$emotion = "good"
		Case "Раздраженный"
			$emotion = "evil"
		Case "Нейтральный"
			$emotion = "neutral"
	EndSwitch
		$url = "https://tts.voicetech.yandex.net/generate?key=c0ed3bf1-0aeb-4202-9fcd-51918b925705&text="&_Encoding_URLToHex($text)&"&format=mp3&lang=ru-RU&speaker="&$golos&"&emotion="&$emotion&"&speed=1.0"
		InetGet($url,$files)
	If FileExists($files) Then
		SoundPlay($files)
		_GuiBlock()
		FileDelete($files)
	Else
		MsgBox(0, "Сообщение", "Не введён текс или сервер не отвечает, повторите попытку позже!")
		_GuiBlock()
	EndIf
EndFunc

Func _GuiBlock()
	If BitAND(GUICtrlGetState($start), $GUI_ENABLE) Then
		GUICtrlSetState($start, $GUI_DISABLE)
		GUICtrlSetState($textedit, $GUI_DISABLE)
		GUICtrlSetState($stop, $GUI_ENABLE)
	Else
		SoundPlay($files)
		GUICtrlSetState($start,$GUI_ENABLE)
		GUICtrlSetState($textedit, $GUI_ENABLE)
		GUICtrlSetState($stop, $GUI_DISABLE)
	EndIf
EndFunc
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
sasha1304
В справке по функции SoundPlay в примечании указано: Если необходимо удалить звуковой файл, то необходимо сначала вызвать SoundPlay(""), чтобы убедиться в том, что дескриптор закрыт. Попробуйте, вдруг поможет ;)
 
A

Alofa

Гость
Как-то так на скорую руку, но надо тестить:
Код:
#include <Sound.au3>
#include <Encoding.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <ComboConstants.au3>
#NoTrayIcon

Global $aSound_ID, $files = @ScriptDir & "\sintez.mp3"

GUICreate("Сентизатор речи", 715, 340, -1, -1)
GUICtrlCreateLabel("Введите текст:", 10, 5, 525, 20, $SS_CENTER)
$textedit = GUICtrlCreateEdit("", 10, 25, 525, 305, $WS_VSCROLL + $ES_WANTRETURN)
GUICtrlSetBkColor($textedit, 0x0000A0)
GUICtrlSetColor($textedit, 0xFFFF86)
GUICtrlSetFont($textedit, 12, "", "", "Comic Sans MS")
GUICtrlCreateLabel("Голос: женский/мужской", 545, 25, 160, 20, $SS_LEFT)
$golos_list = GUICtrlCreateCombo("", 545, 45, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($golos_list, "jane|oksana|alyss|omazh|zahar|ermil", "oksana")
GUICtrlCreateLabel("Эмоции голоса", 545, 70, 160, 20, $SS_LEFT)
$emotion_list = GUICtrlCreateCombo("", 545, 90, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($emotion_list, "Доброжелательный|Раздраженный|Нейтральный", "Доброжелательный")
$start = GUICtrlCreateButton("Прочитать", 545, 120, 160, 20)
GUICtrlSetState($start, $GUI_DISABLE)
$stop = GUICtrlCreateButton("Остановить", 545, 150, 160, 20)
GUICtrlSetState($stop, $GUI_DISABLE)

GUISetState(@SW_SHOW)
Local $textvalid
While 1
	If IsArray($aSound_ID) And (Not StringCompare(_SoundStatus($aSound_ID), 'stopped')) Then _SoundStoped()

	;	ВМЕСТО ЭТОГО БЛОКА:
;~ 	If Not (GUICtrlRead($textedit) == $textvalid) Then
;~ 		If GUICtrlRead($textedit) == "" Then
;~ 			GUICtrlSetState($start, $GUI_DISABLE)
;~ 		Else
;~ 			GUICtrlSetState($start, $GUI_ENABLE)
;~ 		EndIf
;~ 		$textvalid = GUICtrlRead($textedit)
;~ 	EndIf

	;	РЕКОМЕНДУЮ ЭТОТ:
	; Здесь проверка, что в $textedit вообще есть хоть какие-то буквы и числа
	If BitAND(GUICtrlGetState($start), $GUI_ENABLE) Then
		If Not StringRegExp(GUICtrlRead($textedit), '(?i)[[:alnum:]a-ё]') Then GUICtrlSetState($start, $GUI_DISABLE)
	Else
		If StringRegExp(GUICtrlRead($textedit), '(?i)[[:alnum:]а-ё]') Then GUICtrlSetState($start, $GUI_ENABLE)
	EndIf
	
	Switch GUIGetMsg()
		Case $start
			ApiSintezYa(GUICtrlRead($textedit), GUICtrlRead($golos_list), GUICtrlRead($emotion_list))
		Case $stop
			_SoundStoped()
		Case $GUI_EVENT_CLOSE
			_SoundStoped()
			ExitLoop
	EndSwitch
WEnd

Func _SoundStoped()
	If IsArray($aSound_ID) Then
		_SoundClose($aSound_ID)
		$aSound_ID = ''
	EndIf
	FileDelete($files)
	_GuiBlock()
EndFunc   ;==>_SoundStoped


Func ApiSintezYa($text, $golos, $emotion)
	GUISetCursor(15, 1)
	Switch $emotion
		Case "Доброжелательный"
			$emotion = "good"
		Case "Раздраженный"
			$emotion = "evil"
		Case "Нейтральный"
			$emotion = "neutral"
	EndSwitch
	$url = "https://tts.voicetech.yandex.net/generate?key=c0ed3bf1-0aeb-4202-9fcd-51918b925705&text=" & _Encoding_URLToHex($text) & "&format=mp3&lang=ru-RU&speaker=" & $golos & "&emotion=" & $emotion & "&speed=1.0"
	InetGet($url, $files)
	If FileExists($files) Then
		$aSound_ID = _SoundOpen($files)
		If Not @error Then
			_SoundPlay($aSound_ID)
			_GuiBlock()
		EndIf
	Else
		MsgBox(0, "Сообщение", "Не введён текс или сервер не отвечает, повторите попытку позже!")
		_GuiBlock()
	EndIf
	GUISetCursor(-1)
EndFunc   ;==>ApiSintezYa

Func _GuiBlock()
	If BitAND(GUICtrlGetState($start), $GUI_ENABLE) Then
		GUICtrlSetState($start, $GUI_DISABLE)
		GUICtrlSetState($textedit, $GUI_DISABLE)
		GUICtrlSetState($stop, $GUI_ENABLE)
	Else
		GUICtrlSetState($start, $GUI_ENABLE)
		GUICtrlSetState($textedit, $GUI_ENABLE)
		GUICtrlSetState($stop, $GUI_DISABLE)
	EndIf
EndFunc   ;==>_GuiBlock

Проверял на Win10[x64]
 
Автор
S

sasha1304

Новичок
Сообщения
41
Репутация
0
Alofa сказал(а):
Как-то так на скорую руку, но надо тестить:
Код:
#include <Sound.au3>
#include <Encoding.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <ComboConstants.au3>
#NoTrayIcon

Global $iSoundLength, $aSound_ID, $files = @ScriptDir & "\sintez.mp3"

GUICreate("Сентизатор речи", 715, 340, -1, -1)
GUICtrlCreateLabel("Введите текст:", 10, 5, 525, 20, $SS_CENTER)
$textedit = GUICtrlCreateEdit("", 10, 25, 525, 305, $WS_VSCROLL + $ES_WANTRETURN)
GUICtrlSetBkColor($textedit, 0x0000A0)
GUICtrlSetColor($textedit, 0xFFFF86)
GUICtrlSetFont($textedit, 12, "", "", "Comic Sans MS")
GUICtrlCreateLabel("Голос: женский/мужской", 545, 25, 160, 20, $SS_LEFT)
$golos_list = GUICtrlCreateCombo("", 545, 45, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($golos_list, "jane|oksana|alyss|omazh|zahar|ermil", "oksana")
GUICtrlCreateLabel("Эмоции голоса", 545, 70, 160, 20, $SS_LEFT)
$emotion_list = GUICtrlCreateCombo("", 545, 90, 160, 20, $CBS_DROPDOWNLIST + $WS_VSCROLL)
GUICtrlSetData($emotion_list, "Доброжелательный|Раздраженный|Нейтральный", "Доброжелательный")
$start = GUICtrlCreateButton("Прочитать", 545, 120, 160, 20)
GUICtrlSetState($start, $GUI_DISABLE)
$stop = GUICtrlCreateButton("Остановить", 545, 150, 160, 20)
GUICtrlSetState($stop, $GUI_DISABLE)

$textvalid = 0
GUISetState(@SW_SHOW)
While 1
	If IsArray($aSound_ID) And (_SoundPos($aSound_ID, 2) >= $iSoundLength) Then _SoundStoped()
	
	If Not (GUICtrlRead($textedit) == $textvalid) Then
		If GUICtrlRead($textedit) == "" Then
			GUICtrlSetState($start, $GUI_DISABLE)
		Else
			GUICtrlSetState($start, $GUI_ENABLE)
		EndIf
		$textvalid = GUICtrlRead($textedit)
	EndIf

	Switch GUIGetMsg()
		Case $start
			ApiSintezYa(GUICtrlRead($textedit), GUICtrlRead($golos_list), GUICtrlRead($emotion_list))
		Case $stop
			_SoundStoped()
		Case $GUI_EVENT_CLOSE
			ExitLoop
	EndSwitch
WEnd

Func _SoundStoped()
	If IsArray($aSound_ID) Then
		_SoundClose($aSound_ID)
		$aSound_ID = ''
		$iSoundLength = 0
	EndIf
	FileDelete($files)
	_GuiBlock()
EndFunc   ;==>_SoundStoped


Func ApiSintezYa($text, $golos, $emotion)
	GUISetCursor(15, 1)
	Switch $emotion
		Case "Доброжелательный"
			$emotion = "good"
		Case "Раздраженный"
			$emotion = "evil"
		Case "Нейтральный"
			$emotion = "neutral"
	EndSwitch
	$url = "https://tts.voicetech.yandex.net/generate?key=c0ed3bf1-0aeb-4202-9fcd-51918b925705&text=" & _Encoding_URLToHex($text) & "&format=mp3&lang=ru-RU&speaker=" & $golos & "&emotion=" & $emotion & "&speed=1.0"
	InetGet($url, $files)
	If FileExists($files) Then
		$aSound_ID = _SoundOpen($files)
		If Not @error Then
			$iSoundLength = _SoundLength($aSound_ID, 2)
			_SoundPlay($aSound_ID)
			_GuiBlock()
		EndIf
	Else
		MsgBox(0, "Сообщение", "Не введён текс или сервер не отвечает, повторите попытку позже!")
		_GuiBlock()
	EndIf
	GUISetCursor(-1)
EndFunc   ;==>ApiSintezYa

Func _GuiBlock()
	If BitAND(GUICtrlGetState($start), $GUI_ENABLE) Then
		GUICtrlSetState($start, $GUI_DISABLE)
		GUICtrlSetState($textedit, $GUI_DISABLE)
		GUICtrlSetState($stop, $GUI_ENABLE)
	Else
		SoundPlay($files)
		GUICtrlSetState($start, $GUI_ENABLE)
		GUICtrlSetState($textedit, $GUI_ENABLE)
		GUICtrlSetState($stop, $GUI_DISABLE)
	EndIf
EndFunc   ;==>_GuiBlock

Проверял на Win10[x64]

ваш вариант работает. но когда читается много текста например строк 7-10 работать перестаёт. не пойму почему :-\
 
Автор
S

sasha1304

Новичок
Сообщения
41
Репутация
0
Alofa сказал(а):
sasha1304 сказал(а):
... работать перестаёт...
Подправил скрипт.

Спасибо, теперь работает как и было нужно. :ok:


Добавлено:
Сообщение автоматически объединено:

Alofa сказал(а):
sasha1304 сказал(а):
... работать перестаёт...
Подправил скрипт.

извините, ещё один вопрос, почему именно такое условие:
Код:
If IsArray($aSound_ID) And Not StringCompare(_SoundStatus($aSound_ID), 'stopped') Then _SoundStoped()


а не такое например?

Код:
If IsArray($aSound_ID) And _SoundStatus($aSound_ID) == 'stopped' Then _SoundStoped()
 
A

Alofa

Гость
OffTopic:
sasha1304 сказал(а):
... почему именно такое условие...
Оператор "==" учитывает регистр.
Код:
$sString_1 = 'Stopped'
$sString_2 = 'stopped'
MsgBox(262144, 'StringCompare', StringCompare($sString_1, $sString_2) = 0)
MsgBox(262144, '==', $sString_1 == $sString_2)
 
Верх