08 July 2009

Zappy drum patch preview

For those who wanted to hear how the drum synth I'm busy with sounds. Also: witness tangled patching horror doom.

Zappy drum patch (WIP) from basementhum on Vimeo.



I do plan to share it. But I have to find a sensible way to extract and clean it from the mega patch its going to be part of ("crx091081gb@mormo_music aah, #maxmsp the art that takes and takes"), so I'm not sure how soon it'll be.

It's a drum synth along the lines of microtonic or waldorf attack. One sine oscillator with a pitch envelope. One pulse oscillator that's multiplied with the sine for some FM grit. One noise generator. Simple amplitude envelopes for the oscillators. A couple of filters.

One main design consideration was that it should be polyphonic but the drum voices should be triggered by audio signals to keep timing tight. This ruled out the poly~ object since it expects event messages to tell its voices to sound. Instead I'm using a home-rolled voice rotator that mimics poly~ a bit. In the demo you hear though, the patch is being driven by a midi track from Ableton (and so the timing is a bit sloppy).

11 June 2009

MSP: Unexpected message order when signals are involved

05 June 2009

oo.objects released for Max5

The Max5 versions of the oo.objects extension were released today. So I no longer have to keep the code I've written using them secret. I made a short video explaining one reason you might want to investigate this extension.

oo.objects extension for Max/MSP from basementhum on Vimeo.

31 May 2009

Unpredictable Pattern Rearrangement in Max

Deterministic pattern rotation in max from basementhum on Vimeo.

Based on this an approach to rearranging musical passages.

Each rotator expects to receive a list in its left inlet representing a pattern (which might refer to a series of note numbers).

Each time it receives a pattern list, the rotator will rearrange it and output the rearranged list.

Simple rotators can be stacked to give passages which play for a long time before repeating.

The second inlet of a rotator expects a rotation code. This is a three number list that determines how the rotator will rearrange incoming pattern lists.

The first number controls how far to rotate the list,

The second number controls at which index point the rotation should begin at (index positions in the list before this point will not be affected by the rotation).

The third number controls how many measures to skip in between rotations.

Examples:

1 0 0
means that 0 1 2 3 will be rotated to 1 2 3 0 every measure.

1 2 3
Means that 0 1 2 3 will be rotated to 0 1 3 2 every fourth measure.

----------begin_max5_patcher----------
2923.3oc6ckziiaiE9rqeED9RRl33VjZ0MvfAY.lSClSSlSoCZPaQaqzxRBR
z0RGj9297HojrTUx1z1xxpbDpt8hVHe76sPxu2SU8GOLZ773mYYiQeD8qnQi
9iGFMRdHwAFk+8Qi2PedQHMSdYii1tYNKc7D0oRn7EqChV84T1BtpYLIFSMl
fLMjuYKeEOapA52xumkwQ7H5Flr494z.ZXQqEukGx37WRXplZbPDe7Dz34zn
UiKu+MAQAa1tQbIFSJkvhC4UoWxB9prkv3oEWIH9AQPmHGL3cGT00xiRxOZf
uTBim+6+ji2Xww9yGdP7xj1BpHN2Tnx7p.UytNPkw8GT4ZbUfpbGPB4dxAz9
Z5.dqfpqiCny0zA79BpbOKnh8DbyECNN6YIBMNAkPW7E9Z1FMBioPQG2KAEG
W6lNFnX1Hnfa.TrpI+fQgBJxwBn2BBYOxRyBhipzDiFuaTJGbpQnk7MKOici
Q.eWEFu3KL+J55Qi8YK0uEhSXQMc0EuT+JChRRYYrHNkmKzU6U51P9maFBqe
9kzEr8dyMpzFMdUZfebjPHpcmhCWzcBqBoqUM4VdEQzjFtYdbb3bZ5iAYAyC
Y0zAfkKEbinbFOPIOfEWwIC1jjJb8p1V0V+WEsbMufZG+PdC08H3n4nfpmoA
GBrqJRhAdpsvuP7ZUGhC6TzrigLtxDUXl2zNMnj2W.j8GD409LVpomFUDLQ8
gI2HHEeW.oVcDjJhZiLD+bDb0tJr5fecn6yAVOOrzbuXIdOXIoMwRofnEVoB
cSrKds1nswUET6JpMnMN0AssWUYbQ7lMLUruwcMXj6PdaQiY8Fzv81iFNFcA
ZnjC8hp3QN.bnYjTi8LXwmxfc2JPBCh12RCjiCw4aFExh2ltnP0kGLGFi0FS
9rLdPT4Bx90xHUu9BWG36WeAPpcK3mDCVE4BH52zRucVxsgtxsQ+QtsOE7lz
uj62g3sXtl2kx8LckaqdkbKheqmba2u7KIZJ2hX1slbmePX.n1WeF8Ql+mgt
AlD5yTNOMX9VtJTes84u+c0pyFeCimSCyoPn7ZFq69tab+1mzlzeXGJz8D7P
r5wD7XNPvy.AOCD7LPvy.AOCD7LPvy.AOCD7LPvy6wM17W2MR9dci6uWIJ48
JwTuaIB78Jwq2DhtGH3oyI3A6ziI3gLPvy.AOCD7LPvy.AOCD7LPvy.AOCD7
LPvyPE7Lrw8AhRFpfmAhWGpfm6dBdz7YjDacG8LRZ5dMeFIuUP0U4A+y7p9L
RdeAUVmCTUrF0WSw5Oidh9BJdIxmwYohgCD6bAML7ETJillBiV.RQ.1BmNJC
wiQKfSvYnsBF.8CVvoyCYvEmAgKxl9onhtPDCeQ7V05hI6WG4j+.rZN0l345
XBKdx0QtcFrVJJwPYQbXbZIwkdDSaSAmkDaiYdhOXYhMcgCUqESWM+Tukp5Q
qodXCaaa8UlFM7Dm2pOuqvmRoK3K1llB55GogaYGv4PEFwJOvK17hHNexoRd
NQW6cK7ESdd9yHM1v6RHPWmVYfD89BI5aXYYzUrF4m7XzRhym1n3YCWR2q6s
fWRxoRCiYax1BrFVdbjlbi6TZr7JSl8y984vHy9F2cE21+HBeD.wsJdzN4J3
ryQvIa+Pl0Q33WCQQ70ZwjWwuiFbak7CLo88E2S9VvtcVJrBQyQgZlrE07VN
sEXVjGq1NIVlMCpcElJW5JKUlFKS873UqHv0tMP17caT7+yN.f8dwWq8Ps86
g7Z0lIt.154d3xOD1KTWiFy7Ncz3Hykd5Hh69PDQOwiEqYkeixpCwc1UKqNl
d8lTX45d0Gryt4ovx8MIJoYlaMm0qXbF6pIiyld8J4VDnSK41sWI1DcSnhTu
zeRzotnMoeYc6dJnc+Rr0I6rN8qjtoaDv9UtBM0NBX+Rr0MSgsXB7GRTXqvs
cFKD.rx5Ir40GVa+sdWBc1uYOssKk1DuVj1ePAvRCie5PPiSUnwlzckHOV2R
jmX1hPhnjdgezvXQsQKO21vXo16s.JY9VTBOqEQovXpuRlOlgimxtw4hQoqi
sC1tMyH5+lwRPh7n8EQZQ4qYHp+iznEhzfFD4ydFkDmEHlxXBhF4iBxhCE4C
UbkKhSgMGmDG4KuZNaCZYb5F44xSg5zFyOpy90AXubBRxySmrJoE01XON2nm
jFsgzhRbaSM5+KSnMD5.UACHyhcRH8ETTLL2KJNBQQYAaRBYnrW1wJs9ovV8
X0jqgbI4D+eWqgbZSMzu.5lzXN3F4W3mjWQAB+GP0Ejg1vnYaSYSOUkSt+ic
d1aId+UP6XzlZm+IMCzKBuD3eIIowzEqEtPUKPD3qa1lIpbDPAJy7ZFxOdwV
QCB2Lk+QzZNO4ie3CxKaJfpfuX.cJye6G9le71UfX7gLtn8XelKzgYe3ej72
c89Tzmh9WhdTZf.VCrmS.kalRBVvBdD5JJRPVKDeFB5lgBYKEeF.H3JxSwtP
HokFWe+SqCflbSvp0hqAVAkn4fn.rz.QDgkxPCEwK9gokBgH80PeTsmKZSgD
LQFloPReJHLrDkj2lXBCP0krkqtvhy4KuaY27eUAhxaiLzB.0mCAl3TQ4IHD
yUPGiBiiVMA8crGiCeDFaeWIrKaDgCUF3dHleJRzavHh9FDL+HvTYvLW9ron
eQ3nEHNAecJqX7qvV9ZJurJgfA953mN3fMBLmpT5PxFYmvsLHEZy71GjSdZb
npMWRk5BU3.YOHA1WMpd8cBxlRkVLEMrurchmXDlsNdanO.kf8p3x+95SlmI
LdJ5M3pf3NLUfGUaIGdfQgPWPWtDvOPYL+kZ8wOTN7faL0uwg2FZzKEwxj1v
YeIHQz2yY7mXrnxFKaJRZ08LUXOj8QwWvhzQ8oH31EkhkPg.G.CaV0TIey2E
FEZY0ILPhpiorOmpZG3LeJ5+rqcNPyHNkIbRUynFYGLXr4wq1qxRqPktCL9t
NbrocKtr8cEfPiU7X9eHC71S0GbpU7XKrA3FVwtYatau+12.c3QqyM2bD4hJ
ysrfUQvouRfBoEAEpeV52.2LgmlvC93lLtp2l0F.zjpe5zIRwtQHypAHCeUJ
a350+0Unrga2BB1nEsaRgYax1DGyWKrdLj1OFG24JGv5duKs+cv.457GrnZa
tnuaoPrZQKEPa8siZXjWkrl3t1tPexiZSL4GkNMGGUxozwt2NWDlztSPqEpj
WP582YnOK1WYe0mt33dJdFUrIrpTqG5HqMrly1zrVHqGeDju.BKm96b.sIln
116QQEy7buf859ewDUauRyfcY45HeJDvybL7p9Ibcysifhm0htpWO96vw7Mo
N93D3Ua0XtcANpe3x1LgdIorDVjOJqrJwNTZATu4LqGlSOryMvei3kyyqw8h
+F9r723wqVEpwi+kJHkcwqkh0gYC3LMHZycprgwSigsbb7EVjmkWGitM+kZG
8vqMimlSj2wAkb8uUOLbp8sHtgwcWbipnn71pW7tJP80EQUNz91RUqVwrtuJ
mxpZoS81xlp4Rl5MJZskoY5JS3NSlbMzUlL5NbxVGYxra0cN5JScmtywUWYp
C0cVZHSDb2hSlZHS3tUlL0AmbHcptyzQWYpCwIWckoNLV.QG6oNElvyp0cGv
s6DfIaKS4u+PsU0aniW42tPokf0..svcpwOFqafKi9kVEedZUhqhjaWixuco
RqtQY6a.3Yge3YtUvO42tPg0VynJcG7QzYQz3YcqLY1+jIrNpNR2tPLScbGM
63Iy0Q2Y1wgHzYxbhc2JS5rPLrW252okMd2JR5Zg2gdc5HSc6tow5rCexIZL
4LSLq2LaUJNJ+xEJp5Lcic+C75VGQScEoNb2G5rY1tcJYcnZC2swFrv5rXTm
tWlNZLTy9mLQr5exD1p62bCQmcQeBQBrcck6x2Sk+eGyxuUSZgu7mO7+AGHo
VCC
-----------end_max5_patcher-----------



And here's the rotator abstraction:

----------begin_max5_patcher----------
2036.3oc6b01iiZCD9yY+UfhTkZUSOgswfoRmp5ug9wSUmHDuY4NBDAN6c8N
c+2KXLI3r.wIXS71tZ0lDdyd7imYrmGO3u+vhkqy+Jsboyu67AmEK99CKVvO
U8IVHNdwxcQeMNMpjeaKyneIe8mVtp4RL5WY7SmlGsYGsrzws8R4GXoTF6e1
SaJ9kKc9awkdLOiUl7M9E.f24JNcxFdQUU7+FnsTxNrKIqpb3UNnyymEsi+7
K+yhjnzN2dS8Jc+6iXwOkjs8iEzXViz.HtU0qC.x+xOfeP36bc965G4GO7P8
GqTDShy2silwdAnjWjrMIKJ0IMoT5pw4o4EMBRU8SfHLZU0ufX2PR8O7P.TP
0o.0BjxfFxusNdrX65qr3mDP6NLP2fyX+Fb12H3bAMpnHJaKcybgzXKDoQtc
gZfKxPXcIk4DmeHiQKJGDpg7VdMD3G3hIbvHLv2K.b0XsWeXspkuo.arWiBM
+yvvIA0C3RcuSTLK4Y5NZT4gJX+KIURwfdWSp5qtFTE0qGVnF8v1nNh7DNZg
mvntODsPfLBnoptSRoOWoakjm0oJVr7TQyKwF7uoz8p8xzVtUv81z73OS2zo
ObwxMzGUuDx2Sy56ta+P9NSx1WaVjwhXBgtasFcHk8w96Qju9iQwzAe3d6MV
rbaQxl7rZgP5IqOca08AmlA4fRxM+Nxh12yCyxySWGU7bRYx5TpTePkhbTVx
tHFkkzHOP2iOWxt8Eb0vNkkz7K5zKKYTHc9wLNjMP9UGP2yOpIwHlEmaZPjJ
09LOF2DYXyjgLUBDdraLXfuC20YxhVGJM+X0shiG1stxV6R30JmkqqFI8lvM
2AwMvMhaPkvMwTLbkcBqKbaX8u2+dGWSn.FDdmT.abEhPlAHMtBX.YtU.E5b
92IEvexP5e34V+C2MXLC4.j2HtN3p67kF14l6zZ0MFcPb6mRRP6rvqEik1CX
.zOXDb+.iFgb4.sUnRNU5MvgwaqPb3DZrmlIWZR1PSwhW20WueTnL+PQbaGd
6TebjkiMzRVR1wI19gStHb.R23SIa1HOQRNPmrYedktjP.Uzh9Zk65QLURtq
mixY23cUtwph2guRkahUI2H2qQ+1hjaUsK6w.9UgcYsWVsI2hSV0.Z3YnL5Y
5lOVUMUNf+XDiUjr9.qwkYWdGTHZ6diRWkP6665aSyWGkJHA4XEJUWCHF8RZ
vCmPAcw+jf4IAYe5h5IX3LQ8D7kryMUlm7Q.9zT7lB4SJTHuw+zq.9mXNqGc
Jz2ZbrHsGF6El6sHvKwWPyD+e8pCFsk1KRVujBiGJ6sfiv4NL1VbzWv7M+ff
4iOfJERmjKqRt51YFv6NwvhmQoFcXDMJN9vNivwxvF4HynbJBsVLbi++YHKE
deIqxLNKmF+LP7+yHqZXjHP+HAwRYpBRzOSUB+t.qioJnxLP.spHhgpJ1H6h
.BEEaKCrCTk9A6h0DkUR7rK416EjBOhxMvtj6WgFkAJaURdicM6icsiYsX2b
VbZYMKtWl0P5iYMje2TUg.zGyZHHOGbgAASgZMUJk23V6U.2ZaqDCsSHju6b
GqXXSuC4NQeAyIs9uwAxUh+uA.EGpc9fPJAnt2OVL7LAKFXxryUIpKePlJmu
FFI+VkdYkuoKpYdKfYf1ASnZfofSH+6.X9op4sYDzzCL2nIVxoY3c.LKSSho
WH6huHdhCw.Rv.iDcm.UwD2v3SSZX1.0hblQTPmcnLrmU4Y9I.dPNOIukohm
zMf5GLDc7uFQCjAPCWKkNbfm9oC2m29P1WhaVOdhRTuYW4Glup40lmcI2XUI
VFaW4+npvM1tR2Tt3.UQtCrK4lnHd66Ze3MPU4FXWxsxtSrG4VY0D6xKH.dM
xs8.2.UW2D6Rr8T06MvtVVPe26gb+1xTom86g+5yI6cXOkT1lM3+g42dMrw8
wjiuc1ZY20PNYXOg1ZZ2yAX5LrWrxZxux5A2HXzMn1wZ38jZu8FD6U2L7GH3
UoX43a7IG22Sz2BAeZWLXxuYEgtlteGJB1u20yRO3Q8J+4.GVcX00YKPzyaa
B7hXRyWXirUvTydJcq9vDhwwD+t6EQnfWCfRfoAEQVrqGPYv8brCr8GXkNU0
Oil4jm4PihexoIw+e3HuSbGYckWyMZNwJGNmH77KFGKT3PSucF7Nghrw2Uxz
2VkE10F2pr.mRQkiHst8ET+lurtSpNL7a9R62Wq6AuPsrkD5MxjQZxopFXB6
MowVkXFW5cKa7lg5cpdcsetvTmz3rkNjsOJ9yUQI5NxNMoXejoyWWyqmpuV5
nQCichoO0zeGXnsou75MouMTmelt0ATiV+xL3.BDZiNf7755.57soGyGrBHP
OQqHzafyrImHlGtMG5R1bs+OlQW2DiPZ3q9SeUr9bwJhWUrBtAD4rfv7ZBd5
QQfba5A7aPdUGaZmmynmn09RhSkXfbn0fA2cwZdICd8yd2KvdUkoZ20cptAd
+NjdgCtrL44ipG9EI.W.73QSTZ8jVYkwPP2YCA8BU.AqiN5ZPvoJSJnn4EN+
vD5BxD3Nz0cIbhDNqccPUjIDZVwoypt9koP2qSlpCko1sPH+sf.d5fIJrmY9
Ovqzy7p7qjme3Upn46wwLHtIE5HmNZhRKQIyhfYEAOS6ZDS04SlHpLZDgLqx
De7bfJtYm44X3phLMetYAp3kf22MexzYlTC35el0wI1mLATAmNSoy353pnhC
lWXxzQaTcvOd3eEWu2XA
-----------end_max5_patcher-----------

20 April 2009

Joystick DJ


I've been working on a Max/MP patch that's a DJ application controlled by an flight-simulation style analogue joystick. It's working well. I've been using a pre-release version of the OO Objects extension for Max 5 while putting it together--which has dramatically simplified my patching. I plan to share the patch on GitHub after the public release of the OO Objects extension.


04 April 2009

OP-1 at musikmesse 2009




Just got back from Musikmesse in Frankfurt, which I visited with Thomas (Frau Holle).

Saw some interesting stuff. Most interesting was Teenage Engineering's OP-1 prototype/demo.

There are some important parts of the machine's operation that TE are keeping silent about (the sequencer) and other parts where the details are still a little vague, but it was good to get a chance to talk to the Johan, Jens and David about their tiny workstation. It cleared up some questions I had. Here's the bullet point version:

When: the plan is for OP-1 to be available around February-April 2010.

Price: Their plan is to aim for around 600 Euros, but this is subject to change according to manufacturing costs of the final unit.

Export: the unit is envisioned as a portable workstation, with this in mind, an important feature is its ability to export music you create on it in a format you can use in your regular DAW, perhaps for finishing touches or mixdown. It sounded as though this may take the form of a multi-track digital audio render and dump. Synth patterns being rendered to audio files inside the OP-1, that'd be neat.

Battery life: expected to allow about 8 hours of operation. The O-led display is energy efficient, and the screens have been designed to incorporate a lot of black pixels, which come 'for free' as far as battery drain is concerned. The unit will use a special battery (not off-the-shelf kinds like you might use for a gameboy).

Two corners of the device have holes for a carry strap.

The current prototype is slightly greyer than white. Its colour and looks reminded me strongly of the design of robots and space traffic in the Star Wars films. As I mentioned this, Johan pointed to the o-led screen which was displaying a radar-like dotted ring which could have come straight from a rebel alliance powerpoint presentation.

'Teenage Engineering'?: From what I could gather, the way this term is used in Sweden is a good fit for the mentality of learning-by-doing and risk taking to create things which make the world richer. The 'mad inventor' resonance is stronger when you check the rest of TE's fledgling product line which includes a lamp (sensible enough), a singing alarm clock, and a bike with electronic motor sounds.

As with any promising looking machine that's still in development, there's a tendency to project your wishes onto it, which aren't always compatible with the real world constraints of physical possibility, time and cost ('shippingness'). I'll be trying to keep this in check as I watch TE's progress and look forward to the release of the OP-1

Disclaimer: none of this stuff is official, some possibly misunderstood or misremembered, so go to the TE website if you're looking for something more authoritative.

Best of luck guys and thanks for the beers and peanuts.

20 March 2009

'Dynamic Range' logo

What a good idea. The website's a little rough around the edges, but the initiative is very smart. This non profit foundation provides a plugin (currently PC only) which reports the dynamic range of program material (eg. your music). In addition they've designed a Dynamic Range logo that they encourage people to use in release art to display the recorded range of the music.

This is a good idea in a few different ways. The one that I'm most struck by though, is the canny recognition that people like to score and compare 'points'. Almost any metric will work for this purpose (think of 'number of friends' on myspace), and it's a very efficient way to get people interested in the vector that the number describes. I think that 'score-ifying' dynamic range ratings like this is a great way to raise people's consciousness about the problem of the loudness wars.

I'll be adopting this standard as soon as 'Pleasurize Music' (sorry guys, but that's an awful name) release the mac version of the Dynamic Range meter in May.

26 February 2009

Version Control and Max/Msp. Part 3: Synchronisation with Pull and Push

Github Workflow

When sharing code on github you might see yourself as the maintainer of a given project (you may be the one who created the initial version of the project) or you might consider yourself a contributor to a project maintained by someone else.

As far as git and github are concerned, there's no distinction between these two roles in the workflow I'll be describing. But for ease of explanation, I'll refer to two hypothetical github users as maintainer and contributor. And their repositories will be called 'main repository' and 'contributor repository' respectively. These repositories exist on the respective users local machine as well as being mirrored on github, giving four repositories in total.

Assuming that the contributor has already created a clone of the maintainers repository (as described in part 2) a four step cycle describes the sharing of code between github users, and the subsequent synchronising of the publicly available repository. These four steps will usually be performed repeatedly as a project progresses.

1. The contributor 'pushes' the edited codebase from his local repository to his github hosted one (the equivalent of a subversion commit).

2. The maintainer adds the address of the contributors github repository, a new remote source, to a config file in his local repository. This allows him to pull changes from the contributor repository into his own local repository. The contributors work is merged with the maintainers latest version in this step. Usually the codebases are merged automatically, but sometimes conflicts occur, which will be mentioned shortly.

3. The maintainer 'pushes' his newly merged local copy to the main repository mirror on github making the changed version available for other contributors to clone or pull from.

4. The contributor pulls the latest version from the main repository on github, and makes further edits as necessary before repeating the cycle.

Whether you're the maintainer or the contributor the workflow is the same, the distinction we might make between these roles just translates to one of the github repositories being the understood as the 'main' one.

Pull Requests


The workflow described assumes some communication between the maintainer and contributor. At a minimum, the maintainer needs to be informed that changes to the project have been pushed to a contributors github repository, and the contributor needs to be informed that a new version of the project is available at the main repository to ensure that he's working with an up-to-date version of the code.

In the first case, the contributor needs to send a 'pull request' to the maintainer; a pull request is a way of saying "I've made a change/improvement to the project that you might be interested in incorporating into the main repository. You can find my repository at xxx". Technically there's nothing special about pull requests, they could be sent by email. Conveniently, github integrates the sending of pull requests into it's interface by displaying a 'pull request' button; this button appears when you're viewing a repository that you previously 'forked' from a maintainer (as described in part 2). The button can be used to send the maintainer a message which automatically includes the information they need to access your repository.

Passing the Baton


Using a system like github for open source Max projects is great insurance for the future of a project. If a maintainer ever stops acting like a maintainer (if they go silent, or step down for whatever reason) someone else can easily 'pick up' the project without the need for further action by the previous maintainer.

Conflicts


I saved the trickiest part for last. Whenever someone 'pulls' from a repository git attempts to merge the changes from that repository with any changes that might have made been made locally. Usually this merge operation completes successfully, occasionally though human intervention is needed to figure out which edits should be kept and which should be discarded; for instance, when two people have made parallel but different edits to the same object in max. This situation is called a merge conflict.

If a conflict happens while pulling in some new code, git will print a message like this:

CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.


When a conflict happens, git places some special text markers, in the file(s) affected by the conflict; both yours and their versions of the affected code are included. It's up to you to edit and re-save the file in the way you see fit.

Conflict resolution is perhaps the most problematic aspect of putting Max projects under source control. Although we edit patches using a graphic interface, the files we create are text files, and it's into these text files that the conflict markers get added. Since Max's GUI doesn't understand these markers (perhaps in the future it might) we have to do conflict resolution of Max patches in a text editor.

Because it's very difficult to keep a clear overview of what's what while editing the text file of a patch, the most pragmatic approach to conflict resolution in max patches might be to simply decide to keep your or their edit (rather than attempting to mix and match from both), and delete the appropriate chunk of marked code. After the resolved file has been saved, the patch should be tested, and if everything's working satisfactorily, a new commit can be made (see part 1), and pushed to your github repository.

Still; I'd like to find a way to intelligently merge max patches, to make git as useful for max/msp projects as it is for text-based ones. It doesn't seem like a very tough problem, but unfortunately it is one that I lack the knowledge to solve at the moment It's a much trickier problem than I thought! I'll post back with anything that I find out (if you have any clues, please post in the comments).

Posts in this series: Part 1, Part 2, Part 3

15 February 2009

Version Control and Max/Msp. Part 2: Fragmentation vs Collaboration

On top of the benefits for a solo patch creator, version control has even more powerful advantages when it comes to collaborating on a codebase.

Monome culture


People creating max/msp applications for use with monomes tend to be interested in sharing their work and helping one another out; the open hardware approach used by monome fosters this kind of environment. Monome applications spring up regularly. Most of them are written using max/msp.

Tehn, one of the creators of the monome, released a max patch called mlr. Mlr was customised by several of its users. Two of the modified versions were the AES edit, which added a kind of paging system to the top row of buttons, and the cyst edit which added functionality for larger monomes among other enhancements.

In turn, edited versions of these edits emerged, the versions of mlr were multiplying with ingenious improvements and modifications. Yet many of the new functionalities represented by the different versions of mlr were compatible with one another. In principle it would be possible to incorporate most of them in a single version.

There are ways of publishing open source code that encourage cohesion wherever possible by making it easy for editors to submit patches and for the original creators to reincorporate those into a canonical 'main' version. This minimises wasteful splintering of the codebase while still allowing branching into distinct versions, with different aims, when appropriate. One way to do this is to use a version control system like git. I think that the adoption of such a system would be great for max/msp and monome users; in exchange for a small investment getting up to speed with this workflow, it frees up valuable patching/performing/practicing time by removing large chunks of duplicated effort.

I've been experimenting with the combination of git and github, a web-based host for git managed projects, for this purpose. What follows is a brief set of instructions for starting to use this technology in two common situations that arise while working with max/msp.

In either case, some preliminary steps are required. Assuming you've already installed git you'll also need to:

1. Create a public key for your computer
2. Sign up for a github account

Scenario 1: "I wrote a patch. I want to make it easy for others to submit changes to my patch, and for myself to incorporate those into the main codebase"

First create a new public repository at github using the text link shown in the screenshot. Once it's done, github will present you a screen with instructions on what to do next. At the risk of being redundant, here's what to do next. From the github instruction page copy the line that looks like:
git remote add origin [clone_url]

On your local machine, If its not already managed by git, put your project code under git version control. Then, from the project's working directory paste the line you just copied and run that command. This creates an association from your local repository to the one on github which is necessary for the next command.

Run the following to copy your local repository contents to the github hosted repository so that other editors can copy the repository and submit changes:
git push origin master

At this point you should see the files in your last commit listed on the github project page. From now on, continue to commit future changes you make to your project to its local repository, as described in part one, and periodically push them to the github server so that other contributors can always fork (copy) an up to date copy.

Scenario 2: "I want to make a change to someone else's patch (which is hosted on github), and I'd like to give the creator of the patch the option of easily incorporating my change into future revisions of their patch"



First, fork the creators project repository using the button on the github project page. This creates an independent copy of their repository on github's servers. The copy is associated with your account on github rather than the original creators account. Next, copy the address displayed next to 'Your Clone URL:' to your clipboard. On your local machine, open the terminal and navigate to the directory in which you want the project's working directory to be created. When there run the following command (substituting the address in your clipboard)
git clone [clone_url]

Use the files in the cloned working directory as normal to make your edits to the patch and any support files. Commit your changes at sensible intervals according to the instructions in part one, making sure to add any new files you created to the repository.

When the new feature or change is complete, copy your local repository back to its github hosted source repository by issuing the command:
git push origin master

Finally, send a 'pull request' to the creator of the patch via github. This is an invitation for them to 'pull' in the changes contained in your repository, into their own one.

In the final part of this series I'll talk about how to deal with pull requests from contributors to your project.

Posts in this series: Part 1, Part 2, Part 3

Version Control and Max/Msp. Part 1: Delegate Versioning to Git

Some instructions in this post assume the use of OS X, but the principles and steps described are easily transferable to other operating systems.

The image to the left represents two patches in my old max/msp documents folder. Having lost work in the past due to corrupted files, I had gotten into the habit of saving multiple numbered versions of my projects so that if the latest version did become corrupt, I could always return to a previous one and I wouldn't have lost much work.

The obvious costs of doing things this way are that your directories end up a mess, and it can be difficult to make sense of them if you return to a project later. A related but less obvious problem is the broken window effect, worth looking up if you didn't hear about it before.

This is the first area where a version control system can help, even for a patch creator working solo, with no intention of sharing his patches. By using version control we can get rid of messy, multiple numbered files for a single project--while keeping the ability to go back to previous states of our project, should things go wrong. More subtly, using version control leads to the satisfaction of knowing we're Doing Things Properly, or at least trying to.

Here's how a max patch creator, working alone, might use version control. To follow along with the next steps, first install git.

Open the terminal, 'cd' into the directory containing only the project you'd like to put under version control, (first create this container directory if necessary). This will be the directory inside which you make changes to your patch as normal, in git terminology this is your working directory. Execute the following commands, changing the path name as appropriate to cd into your working directory:


$ cd ~/Documents/maxmsp_documents/my_patch
$ git init
$ git add .
$ git commit -m "My first snapshot"

git init creates a hidden directory in the current directory named .git. This folder will be used by git to keep an archive of snapshots of your project. This archive is called a repository.

git add . means 'recursively create a representation all files in directories that are children of the current one, in the index'. Git's index can be thought of as a staging area where a snapshot of your project gets assembled before that snapshot actually gets saved to the repository (committed).

Finally, git commit -m "My first snapshot" tells git to actually create the snapshot that you've prepared. As well as being a verb, a 'commit' is also the name given to a single snapshot in the repository.

Then, you'd continue developing your patch. Regularly, at key stages, you'd return to the terminal to create new snapshots of the project. From your projects' directory:

git add .
git commit -a -m "Added feature X"

'Add' makes sure that any new files you've added to the projects get mirrored in the index, it's not necessary if you know you didn't add new files. Then 'Commit' creates the snapshot as before. The -a option means that before the snapshot is saved, the index will automatically be updated to reflect tracked files that have been modified or deleted.

Then, if something goes wrong, like your patch file becoming corrupted, or just noticing that the recent changes you made were a bad idea. You can take the following steps:
$ git log

This presents a list of all commits from the repository, along with descriptive commit messages. Choose the one that you'd like to go back to and copy the long hash key to the clipboard.
commit 2e8c1eefe6bef04306611c6b06a4a7f324a9f221
Author: mormo
Date: Mon Feb 9 11:36:41 2009 +0100

added multi-press loop button as a test (not yet wired up)

Ctrl+Z exits from the text editor. And allows you to enter the next command, pasting the hash key from the clipboard:
$ git reset --hard 2e8c1eefe6bef04306611c6b06a4a7f324a9f221

This has the effect of discarding all commits after the chosen one, and returning your working directory back to the state represented by that commit.

Getting used to these few commands should mean that you never need to mess with manually adding version numbers to your files again, which means better filesystem hygiene.

In part 2 I'll talk about what version control can mean for projects that involve code sharing. In the meantime, the best article I've found for getting started with git is git magic, well worth a look.

Posts in this series: Part 1, Part 2, Part 3

13 February 2009

mllusc: A mlr clone built in SuperCollider


mllusc: a SuperCollider mlr clone from basementhum on Vimeo

Here's a demo of a monome application I'm calling mllusc. It's pretty basic. It imitates the core functionality of mlr. I'm publishing it in case anyone finds it useful to check the code, improve or build on what's here, and also to try to direct a bit more attention towards SuperCollider as a potential environment for developing monome applications. Unlike Max/Msp, SuperCollider is free. Which means that you don't need to buy anything to take this code and modify it to your own ends, or build something new from scratch.

For any brave souls who do end up venturing into the mllusc code, a disclaimer: At the moment the mllusc structure isn't something I'm proud of. I'm sure there are inconsistencies in there and things that could be done much more sensibly/efficiently. I expect to revisit mllusc in the future, perhaps after the SuperCollider book has been published and I've had a chance to read it through. In the meantime if any SuperCollider wizards are reading, and motivated to help refactor mllusc with a view to creating something more maintainable/extensible, you can find the github repository here: http://github.com/bitbutter/mllusc/tree/master

10 January 2009

Visualising Compression

This post will probably be most useful to those who're learning about the basics of audio processing. I'll explain an approach which I think can be useful for getting to know your compressors (and compression in general) better. This is intended as a supplement to general research material about dynamic range compression.

Visualising Compression
Set up two midi tracks. Have one playing a sustained note. Have the other one repeating a shorter note, as pictured.

Visualising Compression
Assign two synths to those midi tracks. Choose a very simple sound with no effects and a on/off type envelope; a very short attack and release and 100% sustain. Here I'm using instances of Operator playing a single sine wave. Turn the level of the synth playing the sustaining note down, so that it's noticeably quieter than the other part.

Visualising Compression
Record a few measures of the two synths playing. You should get a wave that looks like the one above.

Visualising Compression
Add a compressor to the track containing the wave you just recorded. Add an instance of Smexoscope to your master channel (failing that, you can resample your master channel each time you want to see the compressed wave). Now you can inspect visually the effect that the compressor controls have on the level of the signal over time.

Visualising Compression
Here I'm using Live's built in compressor. I've tuned the threshold so that the louder parts of the synth recording are above it, and the quieter parts fall beneath the threshold. I've set the knee to 100% (sharp) to make sure that nothing beneath the threshold point will get compressed. I'm using a very high ratio with long attack and release times. By experimenting with attack and release while watching the waveform as it's updated, you'll get a clear sense of what these controls are doing. For instance, a medium to high attack combined with a high ratio can give a 'spike' at the onset of the louder parts of the signal. This kind of setting can be useful for adding punch to certain sounds.

Compressors
Here I'm using Audio Damage's Rough Rider, which is capable of more extreme results. Notice the increased distance between the tops of the peaks and the 'squashed' level that follows them, compared to Live's compressor.

25 December 2008

Shalmaneser and SuperCollider

BH: Hi Tim, thanks for agreeing to do this email interview. I'll get started:

You've just released a new Shalmaneser album, TICKER, available for download at http://shaltunes.com. The tracks often have the intricacy of classic Planet Mu or WARP releases, and seem to share the same kind of hazy connection to house. It sounds as though sound design is a very important, but the structure of the tracks perhaps isn't the kind of thing people quickly associate with SuperCollider, the environment you used to create the album. Most SuperCollider works we hear tend to be freeform soundscapes, noise pieces or interactive sonic experiments--there's often a strong academic element there. Your music seems to be coming from a different direction, can you say something about how and why you've ended up using SuperCollider?

TW: Flashback to 1981: I'm 19 years old. Inspired by Tangerine Dream, Klaus Schulze, and Pere Ubu, and possessing spending money for the first time in my life, I troop down to the music store and buy the synthesizer with the most knobs on it, which turned out to be a Crumar DS-2. The first thing I discover is that I can't make those Allen Ravenstine sounds, no matter what I do. Eventually I figure out that this is because the Crumar doesn't allow you to modulate one audio-rate oscillator with another; you can only use the LFO. "Why won't it let me do that?", I ask, for the first but by no means the last time.

Forward to 2003: I've used analog modulars, Csound, and Max/MSP, but none of them have completely satisfied me. Then I read on some mailing list that SuperCollider had gone open-source, and one day when I'm home sick with a nasty cold I decide to download it and try it out. After a couple of hours I realize that I've finally found a tool that would stop me asking that question.

I started by using it for the electroacoustic music I do under my own name. Before long, I got the idea to do algorithmic beat slicing, which led to the material I produce under the name Shalmaneser. I didn't know there was already a third-party library called BBCut for that purpose, so I ended up reinventing the wheel a bit (but also doing some things differently).

So the short answer is that I came to my current style from academic electronic music, and carried over my use of SuperCollider from there. But one of the great things about SC is that it doesn't have a strong stylistic bias--it lets me do what I want to do rather than pushing me in a certain direction.

I do handle compositional structure a little differently, though. Originally, I designed my system for live performance, with controls to let me start and stop synchronized processes in real time. When I started making tracks, I began by writing scores in SC to mimic my live control moves with greater precision, which worked pretty well, but I eventually decided to use Pro Tools as the "tape deck." Now I work a bit like a documentary filmmaker, generating large amounts of raw material in SC and then editing/distilling it down to a tight composition in PT. This also allows me to add acoustic instruments and keyboard lines (also controlling SuperCollider) easily.

BH: Should we be imagining a main SuperCollider program that you use in different ways, or do you use a toolbox of smaller, single-purpose scripts?

TW: The latter. In fact, I often start completely from scratch and doodle around.

BH: Does your software resemble a conventional audio application in the sense of having a GUI or do you 'drive' it from a text console?

TW: For live use I have a screen that shows me what patches are selected, but that's it. If I need real-time control I map it to MIDI sliders.

BH: How distinct are the 'audio generation' and the 'arrangement' activities in your music making? Do you find yourself working for long stretches in one mode and then the other, or are you often switching back and forth between them, with a certain result in mind, as you put a track together?

TW: Between tracks I do a lot of exploratory coding, just messing around with stuff: "I've never used this UGen before, what's it like?" or "maybe the rhythm generator would be even cooler if..." or "let's granulate the radio today."

When I start a track, I'll typically use a few of these scripts as seeds. Some of them also get turned into patches that can be played from the keyboard. But I very quickly get into a back-and-forth mode as the track starts to take shape and demand its own custom material.

BH: I'm interested in the potential of non-realtime processing in SuperCollider stuff for implementing predictive 'look-ahead' audio file modification (but I'm having a bit of a hard time finding many basic examples of this kind of stuff). I wondered if you're using SuperCollider for any non-realtime processing;

TW: I never have. As you point out, there are a lot of interesting possibilities there.

BH: Could you describe one of the scripts that features on the new album, what it does and how you generally use it?

TW: Here's an example (from "Corpsicle Pulse") that's small enough to examine in detail. The idea is to take a drony metallic file and turn it into a rhythm. This is not code I would reuse; it's just a specific solution to a specific problem.


(
{
var tempo, clock, rates, accents, imp, mix, norm, env, accent, unaccent;
b = Buffer.read("...path to soundfile...")

// song tempo in bps
tempo = 125/60;

// sixteenth-note tick
clock = Impulse.ar(tempo * 4.0);

// accent values for rhythm
accent = 1.0;
unaccent = 0.75;

// This will subdivide the clock in a random pattern
rates = Demand.ar(clock, 0,
Dseq(
({[1.0, 4.0, 2.0, 1.0, 1.0, 1.0, 2.0, 2.0].scramble} ! 2).flat * 4.0, inf));

// This accents strong beats
accents = Demand.ar(clock, 0,
Dseq([accent, unaccent, unaccent, accent, unaccent, unaccent, accent, unaccent, unaccent, accent, unaccent, unaccent, accent, unaccent, accent, unaccent], inf)
);

// This drives the percussive envelope
imp = Impulse.ar(tempo * rates);

// Play back five copies of the drone file, slowed down to match
// the song tempo, but with drifting speed for chorusing effect
mix = Mix.fill(5, {
PlayBuf.ar(2, b.bufnum, 125/140 + BrownNoise.kr(0.01)) * 5.levelScale
});

// Remove the natural envelope of the drone
norm = Normalizer.ar(mix);

// Create new percussive envelope with drifting attack and
// decay values
env = Decay2.ar(
imp,
LinExp.kr(LFNoise1.kr(0.23), -1, 1, 0.005, 0.02),
LinExp.kr(LFNoise1.kr(0.3), -1, 1, 0.125, 1.0) * A2K.kr(tempo * rates).reciprocal * 4.0);

// apply to the drone
env * norm
}.play;

)

BH: Thanks for that. I think this is a great example for new SC users to study because it's self-contained and the comments make things very clear.

Is there a technique or idea you're currently excited about exploring in your future SuperCollider creations?

TW: NRT, as you mentioned, is one. I'm also interested in getting more into FFT processing, of which I've done very little, and Ambisonic processing for surround sound. Someday I'd like to do an installation with completely self-running code.

BH: Finally, is there any advice you'd offer to people just starting out in SuperCollider?

TW: Learn how to write classes. It's a bit arcane at first, but once you start creating reusable code, this will make your life much easier.

Join the sc-users mailing list. There's a lot of good information on there, and people are happy to help with questions, even newbie questions.

It's easy to get caught up in programming a grand unified system--there's always just one more thing to add--but don't forget to stop and make music once in a while!

BH: is there anything else you'd like to add?

TW: I'd like to mention that I have a whole bunch of music (electronic and acoustic) available at http://doubtfulpalace.com.

17 December 2008

Sine Interference Beating: A diagram


Sine Interference Beats Diagram from basementhum on Vimeo.
A processing sketch for the SuperCollider workshop I'll be giving. Hopefully it demonstrates the principle of interference beats in an intuitive way; that's when two waves, slightly different in frequency, combine to give a pulsing effect.

09 December 2008

STEIM Jamboree 2008: Opening night

STEIM Jamboree 2008
Yesterday I attended the opening session of the 2008 STEIM Jamboree. I'm ashamed to say that in seven years of living in the west of the Netherlands this was the first time I'd visited STEIM. I met Xndr from machine collective there. He had his wares on display in a side room and was talking about his ideas, components and enclosures.

The first presentation was from Frank Baldé who introduced his latest software creation JunXion v4. I'll be going back to attend a workshop about that at the end of the week so I'll post more about it after that.

In the second presentation David Zicarelli, the CEO of Cycling74, guided us round some of the more user-friendliness-oriented (rounded) corners of max5, taking the chance to talk about the things that are most rewarding and interesting about his job as it's maintainer.

Having had plenty of my own struggles with misbehaving MAX patches, it was quite encouraging to see one of its creators eventually give up trying to get an FM feedback demo patch to work. He remained unflustered after what you might expect had been an unsettling few minutes.

The most interesting part of his presentation, for me, was when he spoke about how he sees the activity of patching. Zicarelli thinks that as builders of systems like the ones associated with MAX, we're involved in a kind of deception. He played a simple patch that responded to mouse movements with a quantized robotic rattle of bargain basement drum sounds. He mentioned his attraction to building systems which manage to facilitate some kind of performative 'magic' to happen, while minimising, or removing completely, the possibility of error (he mentioned his childhood frustration with trying to learn to play the piano).

It wasn't clear whether this was the deception Zicarelli meant, or whether he had more in mind the gentle self-deception we take part in when we try to evaluate how our machines will be experienced by those not 'in the know'. He talked about the switch that happens when creators change roles in this way while they work.

Yesterday evening wasn't the place for it but I think that this kind of discussion isn't complete without addressing the importance of potential error and failure. If a viewer doesn't understand enough about the system being used to answer the question 'How could this performer make an error?' then I think an important channel by which the audience can connect with the performer is closed down, or at least narrowed. It seems that a viewer's understanding of what would constitute an error in the context of a given performance, and their appreciation of the constant proximity of that threat, are important things to facilitate if you're interested in delivering powerful performances. And I think this is why error-proof systems often fail.

Not that this in any way diminishes the usefulness of tools like MAX of course. These thoughts are a reflection of my current interest in creating performance systems that are designed to be learned, and that once the learning is underway, idiosyncrasies of the system might emerge that are rich and interesting enough to earn it the title Instrument.

Sensationally, in the Q&A session Zicarelli responded to a question about the Ableton/Cycling74 project saying that all would be revealed on January the 14th. He added that the project had been in development for two years and hinted that the result would pick up the slack that's accumulated in the pluggo area.