способ звукового сигнала в луа

Страницы: 1
RSS
способ звукового сигнала в луа
 
Добрый день,
Можно воспроизводить звуковые сигналы Windows в скриптах луа так:
звук  из каталога C:/Windows/Media/:
Код
os.execute("powershell -c (New-Object Media.SoundPlayer 'C:/Windows/Media/Alarm10.wav').PlaySync();");
Код
os.execute("powershell -c (New-Object Media.SoundPlayer 'C:/Windows/Media/Ring10.wav').PlaySync();");
 
А знаете ли Вы способ, который не загружает с диска этот файл всякий раз при проигрывании? А делает это один раз в начале работы скрипта
 
Цитата
funduk написал:
А знаете ли Вы способ, который не загружает с диска этот файл всякий раз при проигрывании? А делает это один раз в начале работы скрипта
Знаю, но написал специально эту тему с целью дать вариант простого решения без написания каких-либо вспомогательных функций.
-------------------  
Какой смысл усложнять решение ,
если загрузка этого файла займет микросекунды,
а возможно ОС не будет грузить ее каждый раз снова.  
 
вот вариант многократного проигрывания звука  с однократной загрузкой файла с диска
Код
local x="C:/Windows/Media/Alarm10.wav"
for j=1,10 do
local s="powershell -c (New-Object Media.SoundPlayer "..x..").PlaySync();"
os.execute(s);
end

играет 10 раз файл  "C:/Windows/Media/Alarm10.wav"
 
Код
local x="C:/Windows/Media/Alarm10.wav"
local s="powershell -c (New-Object Media.SoundPlayer "..x..").PlaySync();"
for j=1,10 do  os.execute(s); end
 
Пардон, ошибся
В данной теме написан вариант запуска приложения плеера из командной строки
----------------------------
Т е загрузка файла звука делается приложением плеера.
Т е сначала грузится приложение плеер а оно грузит исполняемый   файл.
---------------------
Основное время затрачивается на загрузку приложения плеер.
Но плюсом такого решения является то, что плеер работает в своем потоке.
----------------------
Вариант
Код
local x="C:/Windows/Media/Alarm10.wav"
local s="powershell -c (New-Object Media.SoundPlayer "..x..").PlaySync();"
for j=1,10 do  os.execute(s); end

Лишь упрощает написание командной строки но не исключает многократную загрузку
=================
Чтобы загрузка была однократной надо использовать функцию на СИ и вызывать ее на исполнения.
-----------------------
При этом если файл длинный, то воспроизведение звука будет тормозить скрипт.
-------------------
Либо надо делать или брать готовую функцию исполняющую в отдельном потоке.
-----------------
В инете есть монго решений.  
 
есть решение
https://quik2dde.ru/viewtopic.php?id=79
Код
function PlaySoundFile(file_name)
  w32.mciSendString("CLOSE QUIK_MP3") 
  w32.mciSendString("OPEN \"" .. file_name .. "\" TYPE MpegVideo ALIAS QUIK_MP3")
  w32.mciSendString("PLAY QUIK_MP3")
end

Но оно делает тоже самое что и мой вариант, но для этого делается спец функция на СИ
т е в этом решении  вызова из командной строки, но через СИ.  
 
Есть еще они способ о котором  возможно мало кто знает.
Я использую такое решение в своих умных устройствах и для отладки звуковых команд для них на луа.
---------------------------
Берем модуль  внешнего плеера (цена вопроса 1 доллар) подключаем его к USB и загружаем на него свои звуковые файлы .
На выход модуля можно подключить динамики.
Есть вариант модуля с памятью на чипе флеш  либо с внешней флеш.
Число таких файлов может быть тысячи
В луа  используется функция вывода на виртуальнуй UART.
Выводим код любого файла и модуль его играет, а скрипт работает дальше.
Время  вывода команды на модуль  несколько мкс.
Кроме музыки, в модуле можно синтезировать предложения .
 
Цитата
nikolz написал:
Кроме музыки, в модуле можно синтезировать предложения .
Круть. На след. этапе можно сделать виртуальную дикторшу.
А для простых смертных у mciSendString предусмотрено проигрывание звука с заданного смещения и заданной длительности.
 
Цитата
Serge123 написал:
Цитата
nikolz написал:
Кроме музыки, в модуле можно синтезировать предложения .
Круть. На след. этапе можно сделать виртуальную дикторшу.
А для простых смертных у mciSendString предусмотрено проигрывание звука с заданного смещения и заданной длительности.
Так Вы ничего и не поняли.
Поясняю.
В начале темы написана одна строчка как воспроизвести звуковой файл.  
--------------------
Тоже самое что и ваша dll на основе  устаревшей функции  mciSendString.
--------------
Т е не надо никаких dll  для этого , понятно?
 
Цитата
nikolz написал:
Т е не надо никаких dll  для этого , понятно?
Из моей темы, где я привёл свой пример на основе w32, было видно, что мне это понятно...
И мне почему-то кажется, что SoundPlayer не может воспроизводить mp3.
 
Мне ваш пример с os.execute и 10-кратным появлением окна цмд перекрыл все стаканы... А если бы у меня в это время пошли сделки? Представляете свою материальную отвественность? :what:  
 
Цитата
Serge123 написал:
Мне ваш пример с os.execute и 10-кратным появлением окна цмд перекрыл все стаканы... А если бы у меня в это время пошли сделки? Представляете свою материальную отвественность?  
Поэтому такой вариант плох. mciSendString - лучше. Либо наприсать свою dll с неустаревшей командой. Можно даже параллельно проигрывать звуки, если использовать правильную команду.
 
Цитата
Nikolay написал:
Можно даже параллельно проигрывать звуки, если использовать правильную команду.
Спасибо, а правильная это какая? У меня создалось впечатление, что mci это не умеет.
 
Цитата
Serge123 написал:
Цитата
Nikolay написал:
Можно даже параллельно проигрывать звуки, если использовать правильную команду.
Спасибо, а правильная это какая? У меня создалось впечатление, что mci это не умеет.
вариант воспроизведения mp3 файлов
скачайте из интернета прогу mpg123.exe
Код
local x="D:/nks/test.mp3" -- звуковой файл
os.execute("D:/mpg123/mpg123.exe "..x)
 
Ещё для смешивания звуков на форумах советовали использовать сторонние звуковые биб-ки или ДиректХ (ДиректСаунд).
 
Цитата
Serge123 написал:
Ещё для смешивания звуков на форумах советовали использовать сторонние звуковые биб-ки или ДиректХ (ДиректСаунд).
могу выложить dll
которая может воспроизводить WAV файлы асинхронно и синхронно из памяти и из файлов.
 
Цитата
Serge123 написал:
Спасибо, а правильная это какая? У меня создалось впечатление, что mci это не умеет.
PLAY

Все указано в документации https://learn.microsoft.com/en-us/windows/win32/multimedia/mci-command-strings
Можно даже проигрывать кусок из файла.

Если проигрывается WAV, то ничего не надо делать более. Если другой формат, то должна быть поддержка. MP3, кажется, тоже проигрывает без доп. усилий.

У меня оповещения на сработавший ордер иногда используются. Если бы это было с блокировкой через команду OPEN или с показом окна терминала, то при одновременном срабатывании нескольких ордеров будет печаль.
 
Цитата
nikolz написал:
могу выложить dll
Программеров интересуют исходники, чтобы не грузить зоопарк посторонних длл (по одной для каждого случая)...
 
Цитата
Nikolay написал:
Можно даже проигрывать кусок из файла.
Я на те страницына сайте МС смотрел, не нашёл, как смешивать звуки.
Я сейчас сделал аналог того, что у меня игралось в dll:
Код
#include <stdio.h>
#include <windows.h>
#include <Mmsystem.h>

int main()
{ if (!mciSendString("OPEN C:\\Windows\\Media\\chord.wav TYPE MpegVideo ALIAS QUIK_MP3", NULL, 0, NULL)) puts("fail");
  mciSendString("PLAY QUIK_MP3", NULL, 0, NULL);
  return 0;
}
Не играет, выдаёт fail. Не пойму, почему это работает в dll для Квика. Такое впечатление, что в консольной программе mciSendString не работает. А у вас как?
Транслировать командой
Код
gcc.exe playsnd.c -o playsnd.exe -O2 -s -lWinmm -m64 -std=c17
Попробовать что-ли с пом. mpeg123 что-то сделать? Она большая, а мне надо мало, ковырять её неохота...
 
Я отправляю команду
mciSendString PLAY "filename"

Если отправить несколько команд, то будет играть сразу все отправленное.
 
Хм, методом тыка убрал ALIAS, как было в w32, устройство взял waveaudio, и звуки стали смешиваться:
Код
static int forLua_mciSendString(lua_State *L)
{ mciSendString("OPEN waveaudio", NULL, 0, NULL);
  mciSendString("PLAY C:\\Windows\\Media\\Alarm09.wav", NULL, 0, NULL);
  mciSendString("PLAY C:\\Windows\\Media\\Alarm06.wav", NULL, 0, NULL);
  mciSendString("PLAY C:\\Windows\\Media\\ringout.wav", NULL, 0, NULL);
//  mciSendString("PLAY C:\\Windows\\Media\\Windows Hardware Fail.wav", NULL, 0, NULL);
  return 0;
}
Т.е., методика такая: один раз выдаём команду OPEN и потом много раз только PLAY, а в OnStop можно выдать CLOSE waveaudio?

Но почему не получается играть файлы с пробелами, как в комментариях??
И почему в консольной программе это всё продолжает не работать???
 
В принципе, получился неплохой подарок к 8 Марта (а чем я хуже женщины?) Но неработоспособность в некоторых случаях омрачает предпраздничное настроение... :what:  
 
Цитата
Serge123 написал:
Хм, методом тыка убрал ALIAS, как было в w32, устройство взял waveaudio, и звуки стали смешиваться:
Код
  static int forLua_mciSendString(lua_State  * L)
{ mciSendString( "OPEN waveaudio" , NULL,  0 , NULL);
  mciSendString( "PLAY C:\\Windows\\Media\\Alarm09.wav" , NULL,  0 , NULL);
  mciSendString( "PLAY C:\\Windows\\Media\\Alarm06.wav" , NULL,  0 , NULL);
  mciSendString( "PLAY C:\\Windows\\Media\\ringout.wav" , NULL,  0 , NULL);
//  mciSendString( "PLAY C:\\Windows\\Media\\Windows Hardware Fail.wav" , NULL,  0 , NULL);
   return   0 ;
}
  
Т.е., методика такая: один раз выдаём команду OPEN и потом много раз только PLAY, а в OnStop можно выдать CLOSE waveaudio?

Но почему не получается играть файлы с пробелами, как в комментариях??
И почему в консольной программе это всё продолжает не работать???
Команда OPEN не нужна, если надо просто проиграть файл. ALIAS не нужен, его и нет в  документации для PLAY.

Чтобы брался путь с пробелами, необходимо путь обрамлять кавычками.
 
Цитата
Serge123 написал:
Цитата
nikolz написал:
могу выложить dll
Программеров интересуют исходники, чтобы не грузить зоопарк посторонних длл (по одной для каждого случая)...
Она одна на все случаи
 
размером в 28 КБайт
 
Для чего в Си и в Луа в путях ставят две обратных косых вместо оной прямой, ведь Виндовс в путях понимает одну прямую косую: C:/Windows/Media/Alarm09.wav?
 
Цитата
Nikolay написал:
Чтобы брался путь с пробелами, необходимо путь обрамлять кавычками.
Попробовал так:
Код
mciSendString("PLAY C:\\Windows\\Media\\\"Windows Hardware Fail.wav\"", NULL, 0, NULL);
Не работает!
 
А в примерах, аналогичных w32, это работало без доп. кавычек...
 
Нет, тут я ошибся, сейчас ещё проверю...
 
Нет, не работают оба варианта:
Код
mciSendString("PLAY C:/Windows/Media/\"Windows Hardware Fail.wav\"", NULL, 0, NULL);
mciSendString("PLAY \"C:/Windows/Media/Windows Hardware Fail.wav\"", NULL, 0, NULL);
 
Тьфу ты, черти мелкомягкие: я так и подозревал, что такой костыль заработает:
Код
mciSendString("PLAY C:/Windows/Media/Windows Hardware Fail.wav type waveaudio", NULL, 0, NULL);
Явная ошибка в парсинге команды...

Сколько времени на эту ерунду потерял вместо того, чтобы что-то полкзное для себя сделать... :what:  
 
Опять ошибся: это другой файл игрался, просто я с него комментарии зачем-то убрал... :what:  
 
Короче, устройство waveaudio почему-то не играет файлы с пробелами, хоть тресни...
 
Вернее, дело не в звуковом устройстве: в упрощённом варианте команд файлы с пробелами не играются, а в той форме, что была у w32, как помню, они игрались.
 
Цитата
Serge123 написал:
Вернее, дело не в звуковом устройстве: в упрощённом варианте команд файлы с пробелами не играются, а в той форме, что была у w32, как помню, они игрались.
Выкладываю исходник на варианте mciSendString
Код
static int mciSS(lua_State*L){
    mciSendString((char*)lua_tostring(L,1),0,0,0); 
   if (lua_gettop(L)>1)SleepEx(lua_tointeger(L,2),1); 
    return 0; }
позволяет воспроизводить файлы wav, MP3, повторять, делать паузу
 
Зачем какие-то дополнительные знаки

PLAY "C:\\Windows\\Media\\Windows Hardware Fail.wav"

Все также как при работе с терминалом. Там тоже надо путь с пробелами обрамлять в кавычки. Весь путь, а не только часть.
 
Цитата
nikolz написал:
  if (lua_gettop(L)>1)SleepEx(lua_tointeger(L,2),1);
Не понял, в чём здесь отличие от простого Sleep?

Цитата
Nikolay написал:
Там тоже надо путь с пробелами обрамлять в кавычки. Весь путь, а не только часть.
Я в #31 обрамлял также часть пути, по-всякому пробовал, не работает! Если у вас работает, то покажите команду из Луа и из Си.
 
Цитата
Serge123 написал:

Я в #31 обрамлял также часть пути, по-всякому пробовал, не работает! Если у вас работает, то покажите команду из Луа и из Си.
Да, но Вы это сделали некорректно. В Lua, если надо передать кавычки, можно использовать апострофы.

И при использовании w32 команда будет выглядеть так:

w32.mciSendString('PLAY "C:\Windows\Media\Windows Hardware Fail.wav"')

Вы же использовали кавычки не в том месте.
 
Цитата
Nikolay написал:
Вы же использовали кавычки не в том месте.
Опять ничего не понял...
Я из Луа по-всякому задавал команды, в т.ч.
Код
playsnddll.mciSendString('play "C:/Windows/Media/Windows Hardware Fail.wav"')
Если есть пробелы, то не работает.
 
Например, это работает:
Код
playsnddll.mciSendString('play "C:/Windows/Media/ringout.wav"')
 
Рассказываю как просто сделать функцию для воспроизведения  звука в различных форматах.
Надо сделать на СИ dll для луа вот с такой функцией.  
Код
static int mciSS(lua_State*L){  mciSendString((char*)lua_tostring(L,1),0,0,0); }
если кто-то не сможет ,пишите - выложу готовую dll.
Далее у меня такая dll называется nks. Вызов функции в скрипте записан как nks.mciss
=================
Поясняю как ее применять:
===========
Чтобы воспроизвести файл  в формате WAV  
надо открыть устройство с этим файлом так:
Код
local file="C:/Windows/Media/Alarm10.wav" -- звуковой файл
nks.mciss("open "..file.."  alias MediaFile wait"); -- открыть устройство
Для воспроизведения содержимого файла  пишем там , где хочется:
Код
nks.mciss("play MediaFile FROM 0 wait");
========================
Чтобы воспроизвести файл  в формате MP3
надо сделать все тоже самое, но для этого файла
Например у меня это файл "D:/nks/test.mp3"
Код
local file="D:/nks/test.mp3" -- звуковой файл
nks.mciss("open "..file.."  alias MediaFile wait"); -- открыть устройство
Для воспроизведения содержимого файла  пишем там, где хочется:
Код
nks.mciss("play MediaFile FROM 0 wait");
Опции :
----------------------------
Если Вам хочется запустить звук и не ждать, когда закончится, то уберите в последней команде "wait"
----------------------------
Если Вам хочется воспроизводить много различных звуков в разных местах скрипта,
то в начале скрипта откройте все звуковые файлы  и  для каждого из них сделайте уникальное имя устройства.
Его надо написать вместо "MediaFile"
Для воспроизведения конкретного файла надо указать имя его устройства в команде воспроизведения вместо  "MediaFile"
==============
Желаю успешного прослушивания звуковых файлов.
 
Цитата
Serge123 написал:
Код
   playsnddll.mciSendString ( 'play "C:/Windows/Media/Windows Hardware Fail.wav"' )
  
Если есть пробелы, то не работает.

Да, Вы правы. Команда Play не поддерживает команды с именами файлов, которые нельзя привести к короткому имени, т.е. с пробелами. Посмотрел внимательно на MCI. Он действительно старый.

Но работает в команде Open.
Т.е. надо подавать две команды
OPEN "C:\\Windows\\Media\\Windows Hardware Fail.wav" ALIAS SND1
PLAY SND1

Для остановки команда
STOP SND1


Также такой подход будет означать, что после команды OPEN, в памяти сохранится ALIAS SND1. И повторно не надо уже открывать. Можно просто заново подать команду PLAY.
 
Цитата
nikolz написал:
Если Вам хочется запустить звук и не ждать, когда закончится, то уберите в последней команде "wait"
Спасибо, выглядит как то, что я запрашивал.
Страницы: 1
Читают тему
Наверх