Arhn - архитектура программирования

Используя RtMIDI, MIDISendSysex не отправляет события на виртуальные порты.

только что начал использовать RtMIDI в Xcode для прототипирования некоторых MIDI-материалов. Он работает нормально, но наткнулся на камень преткновения.

Используя пример midiout.cpp ничего не изменяя:

  • Если я отправляю MIDI-события на уже существующий MIDI-порт, все события отправляются нормально.
  • Если я отправляю MIDI-события на созданный виртуальный порт, отправляются все события, кроме событий sysex.

Взглянув на код библиотеки, все MIDI-события, кроме sysex, отправляются (в OSX) с использованием вызова os MIDIReceived. События Sysex отправляются с помощью MIDISendSysex. Это так и должно быть.

Теперь никаких ошибок не выдается, все выполняется как надо, вызов MIDISendSysex не терпит неудачу — просто никакие sysex-события не приходят к месту назначения. Они просто исчезают в черной дыре!

Кто-нибудь еще сталкивался с этим или у вас есть помощь, предложения, обходные пути?

Спасибо,

(Xcode 4.6.2, OSX 10.9.1, используя MIDIMonitor и MIDIPipe для мониторинга трафика на MIDI-портах, оба показывают одинаковые результаты событий sysex, не поступающих на виртуальные порты из midiout.cpp)

Хорошо, вот маршрут sendMessage, который выполняет фактическую отправку:



    void MidiOutCore :: sendMessage( std::vector *message )
    {
    // ------------------------------------------------------------------------
      // We use the MIDISendSysex() function to asynchronously send sysex
      // messages.  Otherwise, we use a single CoreMidi MIDIPacket.
    // ------------------------------------------------------------------------
    // error handling code removed for brevity

      MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
      CoreMidiData *data = static_cast (apiData_);
      OSStatus result;

    // ------------------------------------------------------------------------
    // IF EVENT IS SYSEX
    // ------------------------------------------------------------------------

      if ( message->at(0) == 0xF0 ) {               // sysex start byte
        while ( sysexBuffer != 0 ) usleep( 1000 );  // sleep 1 ms

       sysexBuffer = new char[nBytes];

       // Copy data to buffer.
       for ( unsigned int i=0; iat(i);

       // build sysex request
       data->sysexreq.destination = data->destinationId;        // destinaiondId is valid endpointref
       data->sysexreq.data = (Byte *)sysexBuffer;
       data->sysexreq.bytesToSend = nBytes;
       data->sysexreq.complete = 0;
       data->sysexreq.completionProc = sysexCompletionProc;
       data->sysexreq.completionRefCon = &(data->sysexreq);

       // send the data
       // this works when we are connected to a 'real' MIDI port/device, but fails on a virtual port
       // destinationId is an endpointref and valid and id is good
       // tried to use data->endpoint (also an endpointref with id) but doesn't send either
       result = MIDISendSysex( &(data->sysexreq) );
       return;
      }

    // ------------------------------------------------------------------------
    // IF EVENT IS NOT SYSEX
    // ------------------------------------------------------------------------

      MIDIPacketList packetList;
      MIDIPacket *packet = MIDIPacketListInit( &packetList );
      packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );

      // Send to any destinations that may have connected to us.
      // this sends to virtual MIDI ports
      if ( data->endpoint ) {
        result = MIDIReceived( data->endpoint, &packetList );
        if ( result != noErr ) {
          errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
          RtMidi::error( RtError::WARNING, errorString_ );
        }
      }

      // And send to an explicit destination port if we're connected.
      // this sends to regular real MIDI devices we are connected to, not virtual ports
      if ( connected_ ) {
        result = MIDISend( data->port, data->destinationId, &packetList );
        if ( result != noErr ) {
          errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port.";
          RtMidi::error( RtError::WARNING, errorString_ );
        }
      }

    }

20.02.2014

  • Пожалуйста, покажите нам пример кода. 20.02.2014
  • Привет! Здесь используется файл midiout.cpp, который поставляется с библиотекой. Я не уверен, сколько я должен опубликовать? Пример программы просто позволяет пользователю выбрать существующий порт или создать виртуальный порт и запускает несколько примеров MIDI-событий для каждого из них. Через секунду выложу ссылку на rtmidi... 20.02.2014
  • rtmidi находится здесь: music.mcgill.ca/~gary/rtmidi с скачать: music.mcgill.ca/~ gary/rtmidi/release/rtmidi-2.0.1.tar.gz. Как я уже сказал, у меня были проблемы с моим кодом, поэтому я вернулся и проверил поведение с помощью примера программы, поставляемой с библиотекой, и это показывает то же самое поведение. 20.02.2014
  • midiout.cpp: dl.dropboxusercontent.com/u/4211158/code/midiout. cpp RtMidi.cpp: dl.dropboxusercontent.com/u/4211158 /code/RtMidi.cpp RtMidi.h: dl.dropboxusercontent. com/u/4211158/code/RtMidi.h RtError.h: dl.dropboxusercontent.com/u/4211158/code/RtError.h 20.02.2014
  • Интересно, что несистемные события отправляются двумя способами: если они подключены к существующему порту, rtmidi использует MIDISend, но если есть конечная точка (виртуальный порт), она также отправляет туда с помощью MIDIReceived. Если я закомментирую отправителя MIDIReceived, то обычные события также не будут отображаться на виртуальном порту. Итак, похоже, это связано с тем, что MIDISendSysex не отображается на виртуальном порту - похоже, что он хочет отправлять только на обычный MIDI-порт, а не на виртуальный. Расследование... 20.02.2014
  • Признаюсь, я понятия не имею о MIDI, даже о XCode. Но лучший способ получить ответы здесь — это создать SSCCE с вашим собственным кодом. 20.02.2014
  • Действительно, но мой собственный код не проблема, это код библиотеки rtmidi или его поведение (на которое я ссылаюсь, если кто-то хочет взглянуть, так как это слишком много для публикации), но вы правы, я думаю может быть, это неправильное место, чтобы получить помощь по этому конкретному вопросу... 20.02.2014
  • Думаю, я свяжусь с автором библиотеки для уточнения поведения. 21.02.2014

Ответы:


1

Дополнительное примечание — это была ошибка в RTMidi, которая должна быть исправлена ​​в следующей версии. Это связано с тем, что в CoreMIDI вызов MIDISendSysex() не отправляет на виртуальные порты, он будет работать только на реальных портах.

Я обновил свою локальную копию RTMIDI для обработки событий sysex с помощью MIDIReceived() в соответствии с рекомендациями этой темы в списке рассылки CoreAdio: http://lists.apple.com/archives/coreaudio-api/2006/Январь/msg00236.html

Теперь он отправляет sysex на виртуальные порты и ведет себя так, как ожидалось.

24.02.2014
  • на самом деле не на 100% правда. Sysex может передаваться через виртуальные порты. Получатель должен соответствовать правилам sysex. Поэтому заголовок должен быть правильно установлен. Зная это, потому что пару месяцев назад я сделал плагин виртуального миди-порта, который получал sysex и при необходимости отправлял обратно для передачи символов текста песни. Когда вы использовали для тестирования возможность, учтите, что DAW, которую вы использовали, может в некоторых случаях не отправлять sysex из коробки. И да на виртуальных портах крутится отправитель и получатель. Таким образом, MIDISendSysex в этом случае бесполезен, MIDIReceived() - это то, что нужно.. правильно! 25.04.2020
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..