npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simple-dog

v1.2.0

Published

The goal of this project is to provide a network adapter for the Linux ALSA Sequencer API.

Downloads

8

Readme

Linux ALSA Sequencer UDP interface

Purpose

The goal of this project is to provide a network adapter for the Linux ALSA Sequencer API.

This project grew out of limitations experienced with MIDI packages in Node.js (issues when using MIDI and networking, or MIDI and Electron, for example), and the lack of up-to-date MIDI packages for Python. It should also be useful to easily integrate third-party, IoT-based devices into the Linux MIDI stack.

This project implements a MIDI-to-UDP interface which allows to receive, send, and control ALSA MIDI Sequencer sentences. The UDP interface is then made available as an API in a separate application; in the present case this package provides a Node.js API, but the implementation is language-agnostic.

The MIDI/UDP gateway is written entirely in C with alsa-lib (what else) and libuv to ensure fast delivery of messages.

Similar work

I am not aware of similar work but would greatly appreciate any references.

This is orthogonal to the purpose of RTP MIDI, in that RTP-MIDI is meant to be used between MIDI instruments (horizontally) while this is meant to be used between a MIDI stack and a non-MIDI environment (vertically).

Prerequisites: Debian, Ubuntu

apt install -y --no-recommends libasound2 libasound2-dev libuv1 libuv1-dev build-essential

Prerequisites: Alpine Linux

apk add musl-dev alsa-lib alsa-lib-dev libuv libuv-dev gcc

Installation

Using npm

npm install simple-dog

Using yarn

yarn add simple-dog

Starting the process

As indicated, this package contains two parts,

  • a Linux ALSA MIDI to UDP gateway written in C
  • an implementation of an API for Node.js.

In the regular case, the gateway is started (on the local host) by the Node.js process.

However the gateway can also be started manually, either on the local machine or on a remote machine.

./bin/alsa-midi-gateway

The process will bind on UDP port 3001 and send messages to UDP port 3002 on localhost by default.

The bind options can be overriden with SOURCE_HOST and SOURCE_PORT environment variables. The remote options can be overriden with DEST_HOST and DEST_PORT environment variables.

API

Either

import {AlsaMidiClient} from 'simple-dog'

or

const {AlsaMidiClient} = require('simple-dog')

new AlsaMidiClient

const midi = new AlsaMidiClient('MIDI')

createPort

Create a new MIDI port for input and output.

const port = await midi.createPort('Port 1')

Create a new MIDI port for input only.

const port = await midi.createPort('Port 1','input')

Create a new MIDI port for output only.

const port = await midi.createPort('Port 1','output')

deletePort

await midi.deletePort(port)

sendMidi

await midi.sendMidi([0x91,0x40,velocity])

portConnect

const client_id = await midi.clientId()
await midi.portConnect(client_id,port, other_client_id,other_port)

portDisconnect

await midi.portDisconnect(client_id,port, other_client_id,other_port)

.on('ready', () => … )

Called when the system is ready to accept commands.

.on('midi', (midi_data) => … )

Receives plain MIDI data.

.on( event, (data) => … )

Receives any ALSA MIDI Sequencer event.

Some of these are standard MIDI events: NOTEON, NOTEOFF, KEYPRESS, CONTROLLER, … START, STOP, … Others are ALSA MIDI specific events: CLIENT_START, CLIENT_EXIT, …

The complete list is available in the source.

Packet Format

Multi-byte values are Big-Endian-encoded.

Message types

  • SD_MSG_MARK (timestamp-only) is sent from the interface to provide real-time timestamp information (MIDI data length = 0).
  • SD_MSG_MIDI (UDP→MIDI out) is sent to the interface to force the output of MIDI content onto the interface; MIDI data length = 0 is used to indicate end of stream, while any other value is parsed and sent out accordingly.
  • SD_MSG_SEQ_EVENT (MIDI in→UDP) is sent from the interface to provide event notifications, based on the ALSA Sequencer specifications.

Common fields

  • offset 0: 1 byte version + time flags
  • offset 1: 1 byte message type (SD_MSG_*)
  • offset 2: 8 bytes for timestamp
  • offset 10: 2 bytes for MIDI data length = M (0 if no MIDI data is included)
  • offset 12: M bytes for MIDI data

Additional fields

For SD_MSG_SEQ_EVENT, the MIDI data might be present or absent (MIDI data length = 0) and the following fields are added:

  • offset 12+M: 1 byte for event type (SND_SEQ_EVENT_* defined in ALSA-lib)
  • offset 13+M: 1 byte for event flags
  • offset 14+M: 1 byte for queue
  • offset 15+M: 1 byte for source client address
  • offset 16+M: 1 byte for source client port
  • offset 17+M: 1 byte for destination client address
  • offset 18+M: 1 byte for destination client port
  • offset 19+M: 1 byte for event data type (SD_TYPE_*, indicates the type of the data event content)
  • offset 20+M: 2 byte for event data length = N // Not sure why I'm doing this, wbuf can only store 128 bytes anyway
  • offset 22+M: N bytes for event data (interpreted per SD_TYPE)