310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
1

Синхронное воспроизведение через mciSendString

13.08.2014, 18:51. Показов 3165. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Для Wav файлов есть sndPlaySound и константы. Иногда нужно выстраивать озвучиваемые файлы в очередь, а в моем случае в этой очереди еще и озвучка текста. Для Wav очень удобно при этом пользоваться SND_SYNC. Но понадобилось мне воспроизводить еще MP3. Выбрал вариант с mciSendString. Но воспроизводит асинхронно, возвращая управление сразу, не дожидаясь окончания звучания. Может кто знает, как придержать дальнейшее выполнение кода, пока файл полностью не проиграет?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.08.2014, 18:51
Ответы с готовыми решениями:

Воспроизведение mp3-файлов через VB
помогите начинающему программеру. хотелось бы узнать какова структура файлов mp3. Как...

Воспроизведение звукового сигнала через определенные промежутки времени
Понятия не имею как это делать( помогёте? В общем, суть программы такова: Таймер. Текстовое...

MciSendString и Windows 10
Не проигрывает mp4 на десятке, ошибок не выдает, кодеки установлены, на семерке и восьмерке полет...

Толковые описания по mciSendString
Фигня это, а не описание, даже пусть и по-английски. Человек конкретна спрашивал толковое (!!)...

32
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
13.08.2014, 19:15 2
Определить статус воспроизведения файла
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
13.08.2014, 23:17  [ТС] 3
Да, думаю что можно гонять цикл с задержкой, и постоянно спрашивать статус. А нельзя ли как с WAV файлами и sndPlaySound? тут можно просто выбрать синхронный или асинхронный режим.
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
13.08.2014, 23:28 4
Лучший ответ Сообщение было отмечено The trick как решение

Решение

Цитата Сообщение от Bagir Посмотреть сообщение
А нельзя ли как с WAV файлами и sndPlaySound? тут можно просто выбрать синхронный или асинхронный режим
Можно - есть флаг wait:
Visual Basic
1
play Music wait
; но это глупо тормозить весь поток, тем более что в MCI есть методы оповещения.
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
14.08.2014, 00:20  [ТС] 5
Да вот пробовал так, и поимел одни тормоза ))
Попробую еще поиграться, но наверное придется гонять цикл, или искать что то другое для mp3

Добавлено через 49 минут
ключ "wait" лишь притормозил сам процесс mciSendString, и поглючил на это время форму (окно моей программы с кнопками и прочей фигней), но сам код vb продолжал исполняться. Более того, следующее задание (файл) для mciSendString был поставлен в очередь (но только именно для него). В общем получилась гадость.
Задача такая: Есть три требования:
1. Озвучивать переданный текст. Проговаривать его с помощью движа.
2. проигрывать Wav файлы
3. проигрывать mp3 файлы
Все это добро ставить в очередь, чтобы одно не перебивало другое.
Для спича у меня есть dll с синхронным восроизведением. Тоесть когда я отправляю что то проговариватья, дальше код не движется, пока предложение не закончиться. Когда отправляю wav файл - тоже самое по средствам Global Const SND_SYNC = &H0 Звук воспроизводится синхронно, и функция не возвращает управления до окончания его проигрывания. Как быть с MP3 я пока не разобрался
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
14.08.2014, 00:30 6
Цитата Сообщение от Bagir Посмотреть сообщение
и поглючил на это время форму (окно моей программы с кнопками и прочей фигней), но сам код vb продолжал исполняться.
Что за ересь? Флаг wait это аналог SND_SYNC, читай. Это тоже самое.
Цитата Сообщение от Bagir Посмотреть сообщение
Как быть с MP3 я пока не разобрался
Также как и с WAV, а WAV также можно проиграть через mciSendString с флагом wait.
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
14.08.2014, 23:40  [ТС] 7
Цитата Сообщение от The trick Посмотреть сообщение
Это тоже самое.
А вот и не тоже! Да, действительно, с добавлением слова "wait", следующая строка исполняется только после окончания звучания файла. НО!
В моей проге первый запущенный экземпляр становится сервером, и висит пока его не закроешь. Вторые экземпляры программы просто передают параметры командной строки (звуковые файлы или текст на озвучку) первому экземпляру по средствам SendMessage Lib "user32.dll". Другими словами есть обработчик событий, который срабатывает по приему сообщения. А вот, если в это время проигрывался mp3 файл, даже не смотря на добавленный "wait", все равно начнется обработка. А в случае с WAV, sndPlaySound и Const SND_SYNC, даже если за время звучания по средствам SendMessage отправить хоть 10 команд, все они встанут в очередь. Обработка не начнется пока не закончится воспроизведение файла. Вот как то так.
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
14.08.2014, 23:43 8
Цитата Сообщение от Bagir Посмотреть сообщение
SendMessage Lib "user32.dll"
Каким образом передается? Ты знаешь что SendMessage игнорирует очередь? Нужно использовать PostMessage для добавления в очередь потока.
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
14.08.2014, 23:50  [ТС] 9
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'Стать сервером
 Public Sub becomeServer()
     Call reg_class
     dummy = CreateWindowEx(0, WINDOW_CLASS, vbNullString, 0, 0, 0, 0, 0, 0, 0, 0, ByVal 0)
 End Sub
 
'Обработка сообщений 
Private Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
   If uMsg = WM_COPYDATA Then
         Dim cds As COPYDATASTRUCT, str As String
         Call CopyMemory(cds, ByVal lParam, Len(cds))
         ReDim buf(cds.cbData - 1) As Byte
         Call CopyMemory(buf(0), ByVal cds.lpData, cds.cbData)
         str = buf 'StrConv(buf, vbUnicode)
         Call gotMessageFromClient(str, wParam)
   End If
   WindowProc = DefWindowProc(hwnd, uMsg, wParam, lParam)
 End Function
 
 Public Sub gotMessageFromClient(ByVal str As String, Optional hwnd As Long)
     debug.print str
 End Sub
Про то что SendMessage игнорирует очередь я не знал. Но тем не менее все сообщения на озвучку и проигрывание WAV идут по очереди. Ничего не пропадает и не накладывается.
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
14.08.2014, 23:56 10
Прикрепи весь код непосредственно клиент-серверного взаимодействия, и прикрепи в качестве проекта. Я его оттестирую и скажу что к чему.
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
14.08.2014, 23:57  [ТС] 11
Спасибо! буду благодарен. Сейчас соберу все в кучку и прикреплю
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
15.08.2014, 00:12  [ТС] 12
Вот весь проект. Там все по модулям разложено. Думаю нет смысла выдирать из него кусок, чтобы потом пытаться заставить его работать. Все что касается отправки и приема сообщений находится только в модуле SendMessage. При запуске на другом компе скорее всего нужно будет выбрать другой движек синтеза речи, т.к. прога помнит последний выбор.
Вложения
Тип файла: zip Tell.zip (1.46 Мб, 9 просмотров)
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
15.08.2014, 01:15 13
Что за кривой способ воспроизведения? Это ужас!
Все воспроизводится последовательно. Во-первых, нужно закрывать файл после воспроизведения; во-вторых нужно давать псевдонимы файлам, если они у тебя будут идти в списке, когда очередной с таким же именем еще играется:
Visual Basic
1
2
3
4
5
6
7
8
9
Public Function myMciPlayFile(aFile As String) As Long
    Dim mAlias As String
    
    mAlias = CStr(Int(Rnd * 100000))
    
    Debug.Print mciSendString("open " & Chr$(34) & aFile & Chr$(34) & " alias " & mAlias, 0&, 0&, 0&)
    mciSendString "play " & mAlias & " wait", 0&, 0&, 0&
    mciSendString "close " & mAlias, 0&, 0&, 0&
End Function
; в-третьих нужно отказаться от этого убогого способа воспроизведения и взаимодействия. А использовать уведомления, создавать свою очередь и в нее пихать нужные файлы (раз уж нужно через командную строку), освобождая вызывающий процесс, чтобы он не висел и не ждал пока его файл проиграется.
Сейчас у тебя, запустив 100 приложений для воспроизведения 100 звуков, последний будет ждать, пока не проиграются все предыдущие 99 файлов (в памяти будут сидеть 100 процессов).
1
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
15.08.2014, 01:24  [ТС] 14
Спасибо за замечания! open - play - close уже вычитал и сделал. А вот про рандомные псевдонимы это фишка. Сейчас добавлю. По поводу освобождения вызывающего процесса это да. Так было бы лучше. Но в очереди кроме звуковых файлов есть еще и текст на озвучку. Так что не думаю что тут это можно обыграть. Да и такой очереди у меня не бывает. Максимум 2-3 вызова. Но конечно надо делать правильно.
К стати, раз уж смотрел весь проект, может подскажешь как сделать выбор звуковой карты? У меня тут только список строится, и показывает которая в винде выбрана основной. Изменить увы нельзя. А для меня это очень важно.
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
15.08.2014, 02:03 15
Цитата Сообщение от Bagir Посмотреть сообщение
У меня тут только список строится, и показывает которая в винде выбрана основной
http://support.microsoft.com/kb/180032
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
15.08.2014, 02:20  [ТС] 16
Если правильно понял, то на форме требуется добавить контрол с именем MMControl1. А если его нет, то как быть? Для проигрывания файлов он мне не был нужен.
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
15.08.2014, 02:24 17
Цитата Сообщение от Bagir Посмотреть сообщение
Если правильно понял, то на форме требуется добавить контрол с именем MMControl1.
Нет.
Смотри справку по mciSendCommand, первым параметром передается ID девайса, который можно получить из строки посредством mciGetDeviceID.
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
15.08.2014, 03:11  [ТС] 18
Пока не получилось.
Нашел обсуждение, где в самом начале получают
Visual Basic
1
2
3
lDevID = mciGetDeviceID("waveaudio")
'затем 
rc = mciSendCommand(lDevID, MCI_SET, MCI_WAVE_OUTPUT, parms)
А так же комментарии
Каждый файл для соединения устройства имеет уникальный идентификатор устройства. Идентификатор "все" устройства является MCI_ALL_DEVICE_ID.

Думаю что такой вариант должен бы работать. Но получаю The command failed.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 Dim mAlias As String
 Dim parms As MCI_WAVE_SET_PARMS
 Dim rc As Long
 ' Specify the soundcard. This specifies the soundcard with a deviceID
 ' of 0. If you have a single soundcard, then this will open it. If you
 ' have multiple soundcards, the deviceIDs will be 0, 1, 2, etc.
 parms.wOutput = 1
 
 mAlias = CStr(Int(Rnd * 100000))
 mciSendString "open " & Chr$(34) & aFile & Chr$(34) & " alias " & mAlias, 0&, 0&, 0&
 lDevID = mciGetDeviceID(mAlias)
 rc = mciSendCommand(lDevID, MCI_SET, MCI_WAVE_OUTPUT, parms)
 If rc <> MMSYSERR_NOERROR Then Debug.Print "The command failed."
 mciSendString "play " & mAlias & " wait", 0&, 0&, 0&
 mciSendString "close " & mAlias, 0&, 0&, 0&
0
Модератор
9235 / 3453 / 854
Регистрация: 22.02.2013
Сообщений: 5,228
Записей в блоге: 78
15.08.2014, 11:14 19
какая ошибка?
0
310 / 10 / 1
Регистрация: 09.10.2012
Сообщений: 52
16.08.2014, 01:18  [ТС] 20
Ошибки в коде нет, но функция mciSendCommand = MMSYSERR_NOERROR, а именно rc=274
Судя по описанию вот оно:
http://stackoverflow.com/quest... ing-an-mp3
Сейчас спать, а потом путем переведу эту страничку. Истина где то рядом )) Но в любом случае радоваться не стоит. Этот способ лишь заставит играть звуковые файлы на нужной карте. Но ничем не поможет в синтезе речи. Там своя библиотека, и выбора карты нет. Одно без другого бесполезно в программе, но весьма поучительно для себя. Так что будет рыть.

Добавлено через 26 минут
Вообще я ранее даже и не читал про выбор устройства вывода для mciSendCommand, потому что искал как это сделать для своего приложения в общем. Т.к. в программе может быть куча разных функций, которые воспроизводят звуки. Не знаю есть ли такой способ, но я ничего не нашел.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.08.2014, 01:18
Помогаю со студенческими работами здесь

Регуляция громкости функцией mciSendString
Здравствуйте, когда то помню мне скинули следующий архив, в котором лежал почти настоящий mpeg...

Воспроизведение mp3 (mciSendString)
Имеем код: case WM_LBUTTONDOWN: if (!bCTT) { bCTT = true;...

Объект WindowsMediaPlayer - синхронное воспроизведение
Здравствуйте! Пишу свой плеер в WinForms и с некоторого момента появилась следующая проблема. После...

mciSendString() необходимо чтобы воспроизведение звука постоянно повторялась
в общем нужно необходимо чтобы воспроизведение звука постоянно повторялось используется функция...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru