MIDI музыка на C#. Часть 1-я.
Разбираясь в вопросах темы "Мелодии на бипере", решил не останавливаться на достигнутом и пошел дальше. Наиболее естественным способом что-то сыграть на компьютере является использование MIDI. Естественно, для разработки профессионального музыкального софта пришлось бы изучать все спецификации и разбираться во множестве технических моментов. Но для того, чтобы написать что-то небольшое и несложное, достаточно иметь базовые представления о том, как это все работает. Вот в этом мы сейчас и будем разбираться. Воспроизводим ноту В деталях этот вопрос описан в статье Making Music with MIDI and C#, так что пересказывать подробно здесь все не буду, опишу тезисно только то, что понадобится для дальнейшего развития темы. Для реализации задуманного нам понадобится три WinAPI функции
Простейший код, который позволит нам воспроизвести ноту до первой октавы будет выглядеть так
Теперь немного о сообщении. Хоть оно и имеет тип int , тем не менее оно состоит из трех частей, по одному байту каждая.
Первый байт сообщения это всегда команда, а вот следующие два - параметры команды и они могут быть, а может их и не быть, или, например может быть только один параметр. Зависит от команды. Например команда, устанавливающая инструмент для канала имеет только один параметр - собственно номер инструмента. Сыграем мелодию Казалось бы, вот теперь выдавай себе команды на взятие клавиш и получай мелодию, как это было на бипере. Единственное, что непонятно, так это как долго будет звучать взятая нота, прежде чем будет взята следующая. Но на самом деле, если мы захотим проиграть последовательно ноты до, ми и соль первой октавы (60, 64 и 67 соответственно) и для этого выполним вот такой код
Для того, чтобы понять как именно работает MIDI-устройство, можно представить себе синтезатор, на котором есть куча клавиш, всевозможных функциональных кнопок, переключателей, ручек, слайдеров. Также к нему может быть подключена педаль и прочие прибамбасы. Для того, чтобы зазвучала музыка, человеку приходится нажимать клавиши, что-то переключать, жать на педаль и так далее. Кроме того, все это делается во времени, и каждое действие должно быть выполнено в определенный момент. Так вот MIDI-устройство - это то же самое, только вместо всех этих нажатий, отпусканий поворотов и т. д. просто отправляются сообщения. Нажал клавишу - отправилось сообщение о нажатии клавиши, отпустил клавишу - сообщение об отпускании клавиши, сменил тембр... дальше ясно. Таким образом, если мы хотим чтобы ноты из примера сверху звучали по полсекунды каждая и сменяли друг друга, то нам надо отправлять сообщения не только о нажатии клавиш, но об их отпускании, причем выдерживая интервалы между этим операциями, чтобы дать нотам позвучать. Команда NoteOff задается как 8x , в отличие от 9x для NoteOn. Здесь также вместо x нужно указать канал на котором надо прекратить звучание ноты, то есть для первого канала это будет 80. И таким образом код, проигрывающий три ноты подряд будет выглядеть так.
Воспользуемся старыми наработками Коль скоро мы выяснили, как исполнять мелодии, было бы неплохо иметь возможность воспроизвести все, что было сделано в предыдущей статье, где речь шла о мелодиях для бипера. В конце концов мелодии подобраны, известны частоты звуков и длительности звуков и пауз, что еще нужно-то? Создадим небольшой плеер для воспроизведения мелодий.
0 . Метод Close, закрывающий открытое устройство. Метод SetInstrument устанавливает интсрумент для первого канала. Здесь мы используем еще одну команду Cx . Опять-таки вместо x используется номер канала, а второй байт представляет из себя номер инструмента, из списка, приведенного здесь.GM 1 Sound Set Для того, чтобы было удобнее пользоваться этим списком, лучше оформить его в виде перечисления. Я воспользовался расширением CustomButtons для Firefox и создал кнопку со следующим кодом
Кликните здесь для просмотра всего текста
Имея такое перечисление можно перегрузить метод SetInstrument вот таким методом.
Ну и наконец метод PlayNote я сделал похожим на метод Console.Beep, за исключением того, что первый аргумент - это не частота, а номер ноты. Таким образом примеры из предыдущей статьи сначала придется обработать, вычислив номер ноты по ее частоте. Вычисление это несложное, метод выглядит так
>> |
Всего комментариев 12
Комментарии
-
оставлю здесь инфу, которая мне была нужна, но здесь не нашёл:
C# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
///--------------------------------------------------------------------| /// MCI /// Проигрывание MIDI(*.mid) на платформе VS C# (Windows) /// (код взят из класса формы Form1) ///--------------------------------------------------------------------: [DllImport("winmm.dll")] private static extern long mciSendString( string strCommand, StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback ); //////////////////////////////////////////////////////////////////////// private static string Alias = ""; public static void playMidi(String fileName, String alias) { if (Alias.Count() != 0) stopMidi(Alias); Alias = alias; mciSendString("open " + fileName + " type sequencer alias " + alias, new StringBuilder(), 0, new IntPtr()); mciSendString("play " + alias, new StringBuilder(), 0, new IntPtr()); } public static void stopMidi(String alias) { if (Alias.Count() == 0) return; mciSendString("stop " + alias, null, 0, new IntPtr()); mciSendString("close " + alias, null, 0, new IntPtr()); Alias = ""; } ////////////////////////////////////////////////////////////////////////
Запись от XLAT размещена 15.10.2020 в 10:50 -
Запись от diadiavova размещена 16.10.2020 в 12:49 -
MIDI музыка в Windows PowerShell ?
Запись от politoto размещена 17.10.2020 в 11:17 -
Вопрос о возможности использования? Напрямую, как мне кажется, вряд ли, в силу того, что тут нужно юзать винапи. Но ничто не мешает написать код на C# и использовать команду Add-Type. Ну и потом, опять-таки, со всем этим есть смысл заморачиваться, если пишешь какую-то музыкальную программу. А какой смысл в такой программе без гуя? Разве что гуй написать на каком-нибудь HTA, и из него уже задействовать пауэршелл. Ради развлечения можно, конечно, поизголяться, но практической пользы от этого я не вижу ))
Запись от diadiavova размещена 17.10.2020 в 11:54 -
Музыкально информировать администратора о результатах выполнения скрипта.
Запись от politoto размещена 17.10.2020 в 13:04 -
Запись от diadiavova размещена 17.10.2020 в 14:52 -
казалось бы чаво проще?!
у меня такой к вам вопрос:
Каким простым способом можно воспроизвести одновременно сразу два(и/или больше) миди-файла *.mid,
например один играет в фоне, а в эффектах что-то звякает???
как я понял в MCI так нельзя, отсюда у меня выше в коде спаренные плеи со стопами.Запись от XLAT размещена 17.10.2020 в 17:50
Обновил(-а) XLAT 17.10.2020 в 17:52 -
Думаю - никаким. Если есть два файла с совпадающим таймингом и прочими прибамбасами (что мне кажется достаточно маловероятным), то при попытке их одновременного воспроизведения они вряд ли совпадут по времени. Но тут надо понимать, что миди-файл фактически аудио-файлом не является. По сути это файл данных. То есть он не содержит данных о звуках, но содержит данные о нотах, а если быть более точным, то о сообщениях и времени когда какое нужно отправить. Поэтому решение задачи состоит в том, чтобы разобрать файлы, то есть извлечь эти данные, привести их к удобоваримому виду, объединить, после чего можно воспроизводить либо способом описанным в этой серии, либо сохранить в один миди-файл и воспроизводить его каким-нибудь стандартным способом. Другого варианта я не вижу, а этот вряд ли можно считать простым, поскольку еще надо разбираться в структуре файлов и т. д.
Запись от diadiavova размещена 17.10.2020 в 18:35 -
FMOD справляется вроде неплохо.
вот по этой причине MCI хорош для мелкой озвучки под спец заточенных утилит.
там и размер побочных ресов, какими являются сами файлы миди желателен незаметного объема.
например, мелодия из к/ф "17 мгновений весны." всего то лишь 2 кбайтаЗапись от XLAT размещена 17.10.2020 в 19:07
Обновил(-а) XLAT 17.10.2020 в 19:09 -
Честно говоря, ничего по этому поводу сказать не могу. Я обработкой аудио никогда не занимался, причем ни с помощью готовых программ, ни, тем более, с помощью самописных. Просто мне идея создания каких-то эффектов путем одновременного запуска нескольких файлов кажется странной.
И уж если речь идет о работе с миди-форматом, то тут открывается куча возможностей именно в том случае, если обработать данные. То есть можно добавить в файл дополнительный канал, в который можно впихнуть любые эффекты, при этом синхронизировав их и по времени и по другим параметрам(тональность, громкость, темп и прочее). Простым такое решение не будет, но, думаю, что и сверхсложным тоже.Запись от diadiavova размещена 18.10.2020 в 11:41 -
ну, если использовать готовые "промышленные" редакторы и если хорошо представлять,
что нужно на выходе, то я не вижу тут ничего сложного.
Цитата:
смотрите:
допустим это не скрипт, а небольшая утилитка, нуждающаяся в простой озвучке,
то естественным простым способом управления вывода разных звуков,
это их проигрывания из готовых файлов от музыкально одаренных спецов(даже необязательно музыкантов).
Как видите речь о удобстве управления этим аудио-хозяйством с точки зрения юзер-кодера и тут с этим всё просто.
Цитата:И уж если речь идет о работе с миди-форматом, то тут открывается куча возможностей именно в том случае, если обработать данные. То есть можно добавить в файл дополнительный канал, в который можно впихнуть любые эффекты, при этом синхронизировав их и по времени и по другим параметрам(тональность, громкость, темп и прочее).
ок,
если хранить не файлах, то тогда в чем хранить?
идиотский вопрос, неправда ли?
Предлагаете придумать некий новый формат с толстым талмудом АПИ,
чтобы франт-прогер мог тыкать ваши каналы в нужные места своей проги обвешавшись секундомерами?
Запись от XLAT размещена 18.10.2020 в 16:38
Обновил(-а) XLAT 18.10.2020 в 16:40 -
Цитата:хм, вот странно, что может быть это странно:
смотрите:
допустим это не скрипт, а небольшая утилитка, нуждающаяся в простой озвучке,
то естественным простым способом управления вывода разных звуков,
это их проигрывания из готовых файлов от музыкально одаренных спецов(даже необязательно музыкантов).
Как видите речь о удобстве управления этим аудио-хозяйством с точки зрения юзер-кодера и тут с этим всё просто.
Второй проблемой может оказаться, например, несовпадение тональностей.
Как это все будет решаться?
Цитата:
Да я вроде нигде ничего подобного не говорил. Я говорил о том, что слияние миди-файлов нужно осуществлять на уровне данных, независимо от того, будет ли результат воспроизводиться путем непосредственного программного взаимодействия с миди-интерфейсом или путем сохранения результатов слияния в файл. О хранении речи вообще не было, хранить можно как результат слияния в том же миди-формате или исходные файлы хранить, это вообще не важно.Запись от diadiavova размещена 18.10.2020 в 23:11