portmidi / portmidi-haskell Goto Github PK
View Code? Open in Web Editor NEWA Haskell module for PortMidi audio library.
License: BSD 3-Clause "New" or "Revised" License
A Haskell module for PortMidi audio library.
License: BSD 3-Clause "New" or "Revised" License
This is a Haskell module for PortMidi audio library, which supports real-time MIDI input and output. ========= ChangeLog ========= Please see CHANGELOG.md. ============ Installation ============ The usual cabal installation steps apply, either: runhaskell Setup.hs configure runhaskell Setup.hs build runhaskell Setup.hs install or simply: cabal install This will install a PortMidi package that contains a Sound.PortMidi module. ============================== Bug reports / Feature requests ============================== Bug reports and feature requests can be created here: https://github.com/PortMidi/PortMidi/issues.
Audacity has a copy of portmidi sources, I think this patch would be interesting to use here:
(More specifically, the modifications of lib-src/portmidi/pm_mac/pmmacosxcm.c
)
There is not much documentation on hackage or in the code, it would be nice to have some example of usage like for this analogue in go.
The only example I found was this old thread in the mailing list, which I tweaked to get to type-check. However, I cannot get output on my midi keyboard. What am I missing?
In the first screenshot, we see that opening an device won't work unless the call to openInput is prefaced by a call to getDeviceInfo. Very strange indeed...
In this second one, we see that calling isLeft on a device will cause it to switch! (but only the first time. It settles into an equilibrium of error.)
Also, I'd like to politely point out that the Left value in an Either should be the erroneous value, and the Right should be the valid one. That is, if one hopes to use Either as a monad.
Thank you,
Ben
The Cabal file says this code is licensed under BSD3
, but the LICENSE file actually contains a Zlib-style license, not a BSD license.
I'd like to see the latest master changes on hackage, I can push the package if needed, but would need to be added to the corresponding hackage maintainer group (to do this, first go here : http://hackage.haskell.org/package/PortMidi/maintain and then click "Maintainer group" and then "Edit").
Thanks!
The Timestamp
(type Timestamp = CULong
) precision is currently milliseconds, which is enough to introduce midi-jitter of up-to one millisecond. I guess that in some applications, it could be audible, and some platforms (OSX for example) provide nanosecond precision for MIDI timestamps, so we could rewrite portmidi to take advantage of the full resolution, where it is available.
I'd like to propose a PR where the full precision is kept.
(After looking at it a bit more, it looks like it's a big task... and we would need some unit tests to make sure nothing is broken.)
Since it's a breaking change, to avoid undetected bugs when upgrading, I think the type should be changed, I propose newtype NanoTimestamp = CULLong
.
What do you think?
Greetings. First of all, I'd really appreciate any help with this issue. I'm ready to do what I can to help.
I'm deserializing inbound sysex from a vintage Yamaha hardware synthesizer, and PortMidi is not giving me the correct stream of inbound bytes. I know what to expect, given the request I've made to the synth. I also have a utility program, PocketMidi (on Mac) that gives the correct bytes. I am 100% sure of a bug, 60% sure it's in the coremidi integration.
I repeatedly poll PMStream until I get a GotData.
I read the PMEvents.
From each PMEvent, I'm taking the message (::CLong), and extracting the first 4 bytes because I read that there are no more than 4 bytes of actual data in each message.
toBytes :: CLong -> [Word8]
toBytes bit64 = map (fromIntegral . f) [0,8..24] --PM:24 not 56; 4 bytes not 8
where
f = \position -> shiftR bit64 position .&. 0xFF
Very simple. BUT what I get back does not look as it should. I took a picture.
Profile gives me the reported bytes sent according to the synth, and the computed number of bytes gotten by taking the length of the packet.
The list within the Profile gives the me timestamped chunks of 4 bytes. Below that, on the command line, I typed what I was expecting.
The second chunk gives me two erroneous trailing zeros, among other issues.
Here's the whole thing typed without timestamps...
Given: F0 43 75 00 00 02 00 00 11 01 20 20 20 6D 6F 6E 6F 20 20 6D 20 38 01 20 64 00 32 02
Got : F0 43 75 00 00 02 11 01 20 20 20 6D 6F 6E 6F 20 38 01 64 00 32 02 00 00
Otherwise, I really like this library. It's fast, and the interface is simple and appropriate.
What do we need to do in order to fix this? It's unlikely that any of you have (or want) my synth, but this problem should be easy to reproduce with any syx-dumping machine.
My modifications introduced regressions on older GHCs (<= 7.8)
I'll try to fix this when I have time.
Also I'd like to introduce a CI script on this github repository to be able to automatically detect those regressions early-on, instead of relying on hackage build matrix for CI :)
Hi, could you submit portmidi to stackage please? I'd like to have tidal-midi in there and portmidi is a dependency.
Instructions are here:
https://www.stackage.org/authors
on hackage there seems to be a changelog: https://hackage.haskell.org/package/PortMidi-0.1.6.1/changelog
As part of #8 I wanted to add a comment in the changelog but couldn't find it. What should I do? Should I create a CHANGELOG file at the root and copy paste what I found on hackage in it?
Today, each call of readEvents
dynamically allocates and deallocates a fixed-size pinned array using allocaArray
, containing 256 PMEvent
s.
Considering that readEvents
is the only exported function allowing to poll / read messages, if a user needs to receive messages at a low latency (say 1 millisecond) then, every millisecond, this function will be called, and even if there is nothing to read, every call will allocate / dallocate, thereby potentially increasing overall memory fragmentation, and maybe also block for some time.
I think we can improve this situation in 2 ways:
Pm_Poll
so that we can first check if there is data before calling the readEvents
call.readEventsToBuffer
that takes an already allocated buffer + its size, and returns an Int
saying how many messages were written to it.What do you think?
Implementation suggestions are welcome, and since I need this in my application I'll probably take a shot at it.
By convention, the Left
constructor of Either
should be used for errors : here, it is used the other way, it's very unsettling :)
We can remove the NoError
(and GotData
?) constructors of PMError
because these non-errors complicate the code at call site. For example, when readEvents
succeeds but has read nothing, it should just return an empty list, and not return a non-error.
All these are breaking changes, but they are necessary to make the code at call site more standard / idiomatic. I think I'll propose a PR soon.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.