Dexus
> Это всего лишь регулировка глубины "колеса" (bend event) в центах (вроде). В
> статье вроде написано :).
> Дефолтовая глубина - два полутона. Я часто использовал октаву.
А что такое вообще колесо? Там частота по мере воспроизведения ноты должна меняться? У меня не меняется вообще.
gammaker
> Там частота по мере воспроизведения ноты должна меняться?
Ты серьезно? Ты хоть спеки MIDI-то читал?
http://www.midi.org/techspecs/midimessages.php
По моему меняется у тебя частота, но не сильно.
Dexus
> Ты серьезно? Ты хоть спеки MIDI-то читал?
Что-то где-то читал, но не здесь. Я просто сделал ноты, инструменты, разобрался с темпом, и думал, что это всё, на остальные события можно забить.
Dexus
> По моему меняется у тебя частота, но не сильно.
У меня ноты - просто сумма синусов\пилообразных волн фиксированной частоты. Я даже представляю, как туда сунуть переменную частоту, чтобы не сломать все оптимизации, с помощью которых я ускорил синтезатор наверное в 50 раз.
gammaker
> Нашёл самый компактный GMGSx.sf2.
> А можно ли фонт чем-нибудь распотрошить и вытащить оттуда только нужные мне
> инструменты?
Для этого есть программа Vienna SF Studio, но не знаю, заработает она без аппаратной поддержки, или нет. Я раньше часто пользовался этой программой, но для работы нужно иметь SB AWE32, Live! или Audigy. Возможно экспортнуть сэмпл в WAV удастся и без этого.
gammaker
как ты обрабатываешь Program Change? Один раз в самом начале на трек? Сохранил в своем редакторе в миди и твой синтезатор тупо игнорит смену инструмента.
Aroch
> как ты обрабатываешь Program Change? Один раз в самом начале на трек? Сохранил
> в своем редакторе в миди и твой синтезатор тупо игнорит смену инструмента.
Не помню, то ли беру первый инструмент, то ли последний. Я считаю, что в каждой дорожке один инструмент. У меня загрузчик midi глючный, всё никак не соберусь доработать. Там придётся как-то хитро разбивать одну дорожку на несколько, потому что у меня музыка хранится как массив дорожек, каждая из которых исполняется одним инструментом.
Поэтому у меня корректно исполняется только формат 1, и то не всегда. Перевожу в формат 1 тупым пересохранением в Anvil Studio. Там же есть пункт меню, чтобы сохранить в формат 0.
Видимо, чтобы правильно обработать midi, надо с ним работать в первоначальном виде, а не конвертить в свой. Слишком там всё запутано.
gammaker
сообщения миди просто изменяют состояние устройства по мере прихода сообщений, не нужно его рассматривать как какую то константу. У себя я просто формирую массив нот, а дальше уже с ними работаю, так проще, в случае чего можно просто отсортировать ноты по инструментам, а их уже в свою очередь по времени нажатия.
Часть парсера для смены инструмента:
int cur_instrument = 1; int instrument_by_ch[16] = {0}; // ... во время парсинга case 0x80: // Note Off midi_file.read(¶m_1, 1); // note number midi_file.read( ¶m_2, 1); // velocity is_note_off_event = true; break; case 0x90: // Note On midi_file.read( ¶m_1, 1); // note number midi_file.read( ¶m_2, 1); // velocity if( param_2 > 0) // add new note { midi_notes[midi_note_count].note = param_1; midi_notes[midi_note_count].time = cur_time_position; midi_notes[midi_note_count].track = cur_track; midi_notes[midi_note_count].channel = midi_channel; midi_notes[midi_note_count].len = -1; midi_notes[midi_note_count].instrument = instrument_by_ch[midi_channel]; midi_notes[midi_note_count].volume = param_2; midi_note_count++; notes_on++; }else{ // note off is_note_off_event = true; } break; case 0xC0: // Program Change midi_file.read( &cur_instrument, 1); instrument_by_ch[midi_channel] = cur_instrument; break; case 0xB0: // Controller midi_file.read( ¶m_1, 1); // controller type midi_file.read( ¶m_2, 1); // controller value if( param_1 == 0x7B) // All Notes Off { // bla bla } break; // ... после свитча if( is_note_off_event) { int n = midi_note_count - 1; for( ; n >= 0; n--) { if( midi_notes[n].note == param_1 && midi_notes[n].channel == midi_channel && midi_notes[n].track == cur_track && midi_notes[n].len == -1) { midi_notes[n].len = cur_time_position - midi_notes[n].time; if( midi_notes[n].len < 0) { midi_notes[n].len = 1; } break; } } #ifdef _DEBUG if( n < 0) { utilities::debug::printf( LogMessageTag::_WARNING, "OpenMidiFile(): IsNoteOff() - can't find note\n"); } #endif }
Aroch
> сообщения миди просто изменяют состояние устройства по мере прихода сообщений,
> не нужно его рассматривать как какую то константу.
Когда я всё это делал, я этого не знал. А когда узнал, уже лень было переделывать. Я пытался сформировать массивы на лету без всяких сортировок.
А вообще у меня появилась такая идея. Сделать класс итератора по midi файлу. Ничего никуда перегонять не надо будет, а итератор будет выдавать подробно сразу всю информацию по каждой ноте вместе с инструментом. И это можно будет легко обобщить на любые источники midi событий. Классы Music и MusicTrack можно будет выкинуть.
gammaker
я хз как у тебя внутри обработка идет. Сортировку я предложил удобства ради, возможно подготовить сэмплы для каждого инструмента по отдельности шустрее чем рандомно, откуда мне знать :) Главное суть ты уловил, что состояние меняется по мере проигрывания.
Aroch
> Сортировку я предложил удобства ради, возможно подготовить сэмплы для каждого
> инструмента по отдельности шустрее чем рандомно, откуда мне знать :)
Ну я имел в виду, что пытался их класть в массив сразу в отсортированном виде без промежуточного массива. Ну в общем ладно, это моё дело, как делать внутри. Когда будет время, переделаю весь парсер midi и исправлю все ошибки.
Я так и не понял, что это за pitch bend? По какому закону меняется частота? Увеличивается или уменьшается, линейно или по параболе? Или ещё как-то?
Новая версия: Синтезатор midi (04.02.2016) + 11 midi. Здесь 11 midi файлов, другие файлы можно достать из архивов старых версий.
Идея приятная, и компактность выглядит очень привлекательной, кажется не все инструменты звучат положенным образом, или же не обрабатывается событие смены инструмента на канале - проверял на своем файле - перегруженных гитар не последовало..
Некоторое время пишу таблатурный редактор, по сути миди редактор для гитар, есть версии под win\linux\android, но везде midi звучит немного по разному, что не может не печалить, потому пытаюсь теперь добавить в него небольшой синтезатор, - в контексте этого процесса тема выглядит интересной мне - буду следить за развитием
constcut
> везде midi звучит немного по разному, что не может не печалить
Наоборот, это радует - есть движение к совершенству, нет одной законсервированной посредственности.
constcut
> кажется не все инструменты звучат положенным образом, или же не обрабатывается
> событие смены инструмента на канале
И то и другое. Многие инструменты ещё не реализованы и вместо них стоят другие. Перегруженной гитары пока нет, вместо неё стоит обычная гитара.
Подумываю о том, чтобы сделать текстовый файл, в котором можно будет описывать инструменты и создавать свои. Это ускорит эксперименты, так как не надо будет перекомпилировать и вообще иметь доступ к исходникам.
А то у меня в исходниках много велосипедов - свои контейнеры, свой аналог std::function, шаблонная магия с использованием фич C++11, которые появились только в 2015 студии, хоть и есть давно в gcc и clang. Поэтому как-то не хочется исходники выкладывать. Но могу сделать dll с сишным интерфейсом, если нужно.
Mikle
> Наоборот, это радует - есть движение к совершенству, нет одной
> законсервированной посредственности.
Там наоборот деградация. В винде хороший синтезатор, в старых телефонах тоже был норм. А в андроиде фиговый совсем. В линуксе вообще нет, надо ставить отдельно.
Тема в архиве.