Awesome! Thanks so much, can’t wait to play with this :stuck_out_tongue: (absolutely worth it!)

What about the PS4 controller? It’s got that very nice touch surface… wonder if that is addressed via HID…

Easy enough to check in Max if you have it. (create an [hi] object and see if it shows up in there). Most gamepads, as far as I know, are all HID compliant, in order to work across the OSs without drivers and such.

A shame is that the [hi] object, in Max anyways, is unidirectional, so there’s no access to vibration/haptics and/or LEDs on the controller itself, which would be super fucking useful.

3 Likes

that would be oh so amazing to get bidirectional communication!

1 Like

Totally.

I don’t actually know anything about HID on linux and/or SC, but I wonder if it’s bidirectional.

(I looked into getting a custom bi-directional HID solution for Max going a few years ago, but it never really materialized)

1 Like

Absolutely it’s possible. I remember messing around with LOVE2D when i was dabbling with Lua last year, and built a game that had haptic feedback. This was on a Debian system with nothing fancy, so assuming it’s just standard HID.

10 Likes

HID in SuperCollider is bidirectional - you should be able to set the value of any element that’s exposed as one that can receive input. I haven’t tried it with a ton of devices, but I was recently able to pick up all the data streams from a multitouch monitor pretty effortlessly - in terms of bidirectional, the most I’ve been able to do is make an LED blink, but I don’t have much to test with.

3 Likes

man, I remember Electro Man. It was surprisingly interesting: more puzzly than platformy. Irritating sounds, though!

1 Like

bidirectional communication

yes it’s possible.

on norns we are using libudev directly for HID. most HID output is leds and force feedback. these have standard sysfs interfaces.

however a lot of device have non-standard interfaces. for example i have an xbox360 controller, and it has LEDs on it, but you can’t just set the brightness of these LEDs directly like you can with lock indicators on keyboards. instead you can set different blinky patterns for the leds through some undocumented mapping on some undocumented port that doesn’t even get enumerated in the events list for the device (it is absolutely not worth my time to figure this out.)

here’s the full list of event codes we get for the xbox360 and a usb keyboard:

Controller
  0 : 0 (EV_SYN) : 
  1 : 1 (EV_KEY) : 
      0 : 304 (BTN_SOUTH)
      1 : 305 (BTN_EAST)
      2 : 307 (BTN_NORTH)
      3 : 308 (BTN_WEST)
      4 : 310 (BTN_TL)
      5 : 311 (BTN_TR)
      6 : 314 (BTN_SELECT)
      7 : 315 (BTN_START)
      8 : 316 (BTN_MODE)
      9 : 317 (BTN_THUMBL)
      10 : 318 (BTN_THUMBR)
  2 : 3 (EV_ABS) : 
      0 : 0 (ABS_X)
      1 : 1 (ABS_Y)
      2 : 2 (ABS_Z)
      3 : 3 (ABS_RX)
      4 : 4 (ABS_RY)
      5 : 5 (ABS_RZ)
      6 : 16 (ABS_HAT0X)
      7 : 17 (ABS_HAT0Y)
  3 : 21 (EV_FF) : 
USB Keyboard
  0 : 0 (EV_SYN) : 
  1 : 1 (EV_KEY) : 
      0 : 1 (KEY_ESC)
      1 : 2 (KEY_1)
      2 : 3 (KEY_2)
      3 : 4 (KEY_3)
      4 : 5 (KEY_4)
      5 : 6 (KEY_5)
      6 : 7 (KEY_6)
      7 : 8 (KEY_7)
      8 : 9 (KEY_8)
      9 : 10 (KEY_9)
      10 : 11 (KEY_0)
      11 : 12 (KEY_MINUS)
      12 : 13 (KEY_EQUAL)
      13 : 14 (KEY_BACKSPACE)
      14 : 15 (KEY_TAB)
      15 : 16 (KEY_Q)
      16 : 17 (KEY_W)
      17 : 18 (KEY_E)
      18 : 19 (KEY_R)
      19 : 20 (KEY_T)
      20 : 21 (KEY_Y)
      21 : 22 (KEY_U)
      22 : 23 (KEY_I)
      23 : 24 (KEY_O)
      24 : 25 (KEY_P)
      25 : 26 (KEY_LEFTBRACE)
      26 : 27 (KEY_RIGHTBRACE)
      27 : 28 (KEY_ENTER)
      28 : 29 (KEY_LEFTCTRL)
      29 : 30 (KEY_A)
      30 : 31 (KEY_S)
      31 : 32 (KEY_D)
      32 : 33 (KEY_F)
      33 : 34 (KEY_G)
      34 : 35 (KEY_H)
      35 : 36 (KEY_J)
      36 : 37 (KEY_K)
      37 : 38 (KEY_L)
      38 : 39 (KEY_SEMICOLON)
      39 : 40 (KEY_APOSTROPHE)
      40 : 41 (KEY_GRAVE)
      41 : 42 (KEY_LEFTSHIFT)
      42 : 43 (KEY_BACKSLASH)
      43 : 44 (KEY_Z)
      44 : 45 (KEY_X)
      45 : 46 (KEY_C)
      46 : 47 (KEY_V)
      47 : 48 (KEY_B)
      48 : 49 (KEY_N)
      49 : 50 (KEY_M)
      50 : 51 (KEY_COMMA)
      51 : 52 (KEY_DOT)
      52 : 53 (KEY_SLASH)
      53 : 54 (KEY_RIGHTSHIFT)
      54 : 55 (KEY_KPASTERISK)
      55 : 56 (KEY_LEFTALT)
      56 : 57 (KEY_SPACE)
      57 : 58 (KEY_CAPSLOCK)
      58 : 59 (KEY_F1)
      59 : 60 (KEY_F2)
      60 : 61 (KEY_F3)
      61 : 62 (KEY_F4)
      62 : 63 (KEY_F5)
      63 : 64 (KEY_F6)
      64 : 65 (KEY_F7)
      65 : 66 (KEY_F8)
      66 : 67 (KEY_F9)
      67 : 68 (KEY_F10)
      68 : 69 (KEY_NUMLOCK)
      69 : 70 (KEY_SCROLLLOCK)
      70 : 71 (KEY_KP7)
      71 : 72 (KEY_KP8)
      72 : 73 (KEY_KP9)
      73 : 74 (KEY_KPMINUS)
      74 : 75 (KEY_KP4)
      75 : 76 (KEY_KP5)
      76 : 77 (KEY_KP6)
      77 : 78 (KEY_KPPLUS)
      78 : 79 (KEY_KP1)
      79 : 80 (KEY_KP2)
      80 : 81 (KEY_KP3)
      81 : 82 (KEY_KP0)
      82 : 83 (KEY_KPDOT)
      83 : 86 (KEY_102ND)
      84 : 87 (KEY_F11)
      85 : 88 (KEY_F12)
      86 : 89 (KEY_RO)
      87 : 92 (KEY_HENKAN)
      88 : 93 (KEY_KATAKANAHIRAGANA)
      89 : 94 (KEY_MUHENKAN)
      90 : 95 (KEY_KPJPCOMMA)
      91 : 96 (KEY_KPENTER)
      92 : 97 (KEY_RIGHTCTRL)
      93 : 98 (KEY_KPSLASH)
      94 : 99 (KEY_SYSRQ)
      95 : 100 (KEY_RIGHTALT)
      96 : 102 (KEY_HOME)
      97 : 103 (KEY_UP)
      98 : 104 (KEY_PAGEUP)
      99 : 105 (KEY_LEFT)
      100 : 106 (KEY_RIGHT)
      101 : 107 (KEY_END)
      102 : 108 (KEY_DOWN)
      103 : 109 (KEY_PAGEDOWN)
      104 : 110 (KEY_INSERT)
      105 : 111 (KEY_DELETE)
      106 : 113 (KEY_MUTE)
      107 : 114 (KEY_VOLUMEDOWN)
      108 : 115 (KEY_VOLUMEUP)
      109 : 116 (KEY_POWER)
      110 : 117 (KEY_KPEQUAL)
      111 : 119 (KEY_PAUSE)
      112 : 121 (KEY_KPCOMMA)
      113 : 122 (KEY_HANGEUL)
      114 : 123 (KEY_HANJA)
      115 : 124 (KEY_YEN)
      116 : 125 (KEY_LEFTMETA)
      117 : 126 (KEY_RIGHTMETA)
      118 : 127 (KEY_COMPOSE)
      119 : 128 (KEY_STOP)
      120 : 129 (KEY_AGAIN)
      121 : 130 (KEY_PROPS)
      122 : 131 (KEY_UNDO)
      123 : 132 (KEY_FRONT)
      124 : 133 (KEY_COPY)
      125 : 134 (KEY_OPEN)
      126 : 135 (KEY_PASTE)
      127 : 136 (KEY_FIND)
      128 : 137 (KEY_CUT)
      129 : 138 (KEY_HELP)
      130 : 183 (KEY_F13)
      131 : 184 (KEY_F14)
      132 : 185 (KEY_F15)
      133 : 186 (KEY_F16)
      134 : 187 (KEY_F17)
      135 : 188 (KEY_F18)
      136 : 189 (KEY_F19)
      137 : 190 (KEY_F20)
      138 : 191 (KEY_F21)
      139 : 192 (KEY_F22)
      140 : 193 (KEY_F23)
      141 : 194 (KEY_F24)
      142 : 240 (KEY_UNKNOWN)
  2 : 4 (EV_MSC) : 
  3 : 17 (EV_LED) : 
      0 : 0 (LED_NUML)
      1 : 1 (LED_CAPSL)
      2 : 2 (LED_SCROLLL)
  4 : 20 (EV_REP) : 

the EV_LED codes for the keyboard are standard and easy to use.

you may notice the EV_FF field for the gampad. force feedback can be pretty deep, some devices let you program custom waveforms and stuff, some don’t. start on page 20 here: http://www.infradead.org/~mchehab/kernel_docs_pdf/linux-input.pdf

anyway, we haven’t made glue to send events to HID devices from lua just yet, but have kept it in mind with the supported-events scaffolding. (e.g., lua knows about those EV_LED fields.)

partly that’s because the use cases just aren’t clear (custom HID controllers? better to use serial maybe, like monome controller protocol) and we are spread thin implementing core functionality. so i hope that the first time someone comes a long with a compelling use case, they can help specify which exact output event bits would be most helpful to implement.

2 Likes

not totally sure i understand the question. the SoC is a Broadcom BCM2837. if you’re curious about the microarchitecture / instruction set, it is four Arm Cortex-A53 cores. the instruction set includes NEON SIMD. (other Cortex variants have “DSP extensions” for SIMD but for A53 it’s all NEON.) there is also the Compute Library if you are interested in doing custom heavy-lifting ML tasks on this platform.

this is most applicable if you want to do very low-level development, probably using assembly. when compiling a program (like supercollider), the compiler (gcc) will take advantage of vectorized NEON instructions when possible.

curious if it could replace my aleph craving for simpler/lighter dsp tasks.

if you mean you just wanna write some C code to do simple audio processing, yes absolutely. supercollider is provided and is a convenient high-level framework for defining musical processing. the norns lua environment is provided and is a convenient way to define knob/key/screen <-> grid/hid/midi <-> osc mapping. but you are not obliged to use either one.

one thing aleph can do that is unique is provide minimal I/O latency. norns can’t do that, it runs on ALSA/jack and has a configurable I/O buffer size that you may want to adjust depending on your specific latency/load requirements.

3 Likes

Ah right, for some reason I thought this was gonna be along the same lines as the Aleph in that regard. For the I/O buffer size, is it going to be in the ‘normal soundcard’ range? (rather, how low can you (reasonably) go under realistic load?)

1 Like

currently the default is 128 frames per period, 2 periods/buffer, at 48k. smaller buffers are possible but the loss of efficiency becomes noticeable below that.

as far as acoustic delay, this is <2ms (sorry, 8ms for total round-trip) and is about the same as standing 1 4 meters away from a sound source.

imho this is mainly an issue if you want to use the audio I/O in a direct feedback loop (which won’t give you resoance > 500hz ~120hz), or in a direct wet/dry mix (which will cause very noticeable comb filtering - so just don’t try to mix dry signal with the same signal routed through the norns and unprocessed.)

6 Likes

To be fair, that’s assuming the total buffer (in + out) is 128 samples (e.g. a 64 sample input buffer and a 64 sample output buffer). Otherwise you need to double that number.

Also, the DAC and ADC chips have a latency on the order of a few samples as well, usually between 7 and 30 depending on the oversampling and their digital filter implementation.

1 Like

But you can’t escape that independently of what silicon you have doing the processing.

Thanks @zebra, I was looking for more details like this. Definitely not planning on asm and sc seems like a good platform for dsp ideas, I’m certain there is a wealth of patches by the community. I’ve been exploring ML approaches to sound, so it was nice to find out they have a library one can use. That said, my use of ML is to ultimately drive dmx lights…

1 Like

To be fair, that’s assuming the total buffer (in + out) is 128 samples (e.g. a 64 sample input buffer and a 64 sample output buffer). Otherwise you need to double that number.

you’re right, double it for round-trip. my bad. additionally i forgot that jack uses this weird “periods” concept, so double it again call the total round-trip latency ~8ms, or 4 meters in air. pushing the Haas effect limit a little but still within it. (i might play with adding one period/buffer and halving the period size.) [update: yea its actually quite happy with 3x 32-frame periods if latency is a priority over power.]

Also, the DAC and ADC chips have a latency on the order of a few samples as well, usually between 7 and 30 depending on the oversampling and their digital filter implementation.

that’s true. for the CS4270 it’s ~5 samples for the ADC and ~2.5 samples for the DAC. and since we’re being pedantic i’ll point out that this is group delay, not latency. (it is frequency-dependent.)

3 Likes

Could one have norns run an external audio interface?

To answer your question, I just found a few posts in this thread :

:slight_smile:

4 Likes

I think our best bet of getting DMX output on the norns is using OLA. I’ve used SuperCollider to control DMX via OSC to OLA with great success.

3 Likes

Do I understand correctly that you can plug those supported devices and basically Ola talks to them if You feed ola osc?

Right now I made a teensy coupled to a screen driving dmx out but I also have an enttec USB device that’s on that list…

1 Like

Yes! It is really simple once you get it installed. a simple osc message like /dmx/universe/0/1 will address the light on channel 1. I made a simple pseudoclass called BusToOSC which enables me to poll control buses and send their values to specific OSC addresses. It’s really helpful for making the connection from SC to OLA. But obviously you wouldn’t even need to use SC if you didn’t want to.

4 Likes