Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gamepad module #1223

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

Add Gamepad module #1223

wants to merge 15 commits into from

Conversation

nkymut
Copy link
Contributor

@nkymut nkymut commented Nov 26, 2024

Adds gamepad support for Strudel, allowing users to use game controllers as expressive input devices for live coding music.

Examples

const gp = gamepad(0) //initialize gemepad

// Use button values to control amplitude
$: stack(
  s("[[hh hh] oh hh oh]/2").gain(gp.tglX).bank("RolandTR909"), // X btn for HH
   s("cr*1").gain(gp.Y).bank("RolandTR909"), // LB btn for CR
  s("bd").gain(gp.tglA).bank("RolandTR909"), // A btn for BD
  s("[ht - - mt - - lt - ]/2").gain(gp.tglB).bank("RolandTR909"), // B btn for Toms
  s("sd*4").gain(gp.RB).bank("RolandTR909"), // RB btn for SD
).cpm(120)

// Use analog stick for continuous control
$: note("c4 d3 a3 e3").sound("sawtooth") 
  .lpf(gp.x1.range(100,4000)) 
  .lpq(gp.y1.range(5,30))
  .decay(gp.y2.range(0.1,2))
  .lpenv(gp.x2.range(-5,5))
  .cpm(120)

// Define button sequences
const HADOUKEN = [
  'd',               // Down
  'r',               // Right
  'a',               // A
];

const KONAMI = 'uuddlrlrba' //Konami Code ↑↑↓↓←→←→BA

// Check button sequence (returns 1 when detected, 0 when not within last 1 second)
$: s("free_hadouken -").slow(2)
.gain(gp.btnSequence(HADOUKEN)).room(1).cpm(120)

// hadouken.wav by Syna-Max
//https://freesound.org/people/Syna-Max/sounds/67674/
samples({free_hadouken: 'https://cdn.freesound.org/previews/67/67674_111920-lq.mp3'})
`} />

Testing Done

  • Tested with Logitech Gamepad F310
  • Tested with Xbox controller
  • Tested with PS4/PS5 controller
  • Tested with Nintendo Switch controller

@nkymut nkymut changed the title Add GamePad Module Add Gamepad module Nov 26, 2024
@felixroos
Copy link
Collaborator

this is super cool, I have to test this. I especially like that you can do sequences!
I can test it with my gamepads as well. A docs page for this would also be very good (similar to the README).

@nkymut
Copy link
Contributor Author

nkymut commented Dec 17, 2024

Thanks! I’m glad you liked the key sequences.
I’ve added a documentation page, and I’m hoping that other input methods—such as MIDI-in or serial input—can also be documented on the same page.

@felixroos
Copy link
Collaborator

is this ready for merge? we can test the controllers when its live i guess

@felixroos felixroos added the v1.2 label Jan 24, 2025
@felixroos
Copy link
Collaborator

currently testing it with my snes gamepad. only the blue (X) buttons seems to work, not sure why. can test more later. I also wonder why we need to poll the gamepads in an animationframe? could we only poll it inside the signal? it might save some work. i can try to do that if you also think it's worth trying

@nkymut
Copy link
Contributor Author

nkymut commented Jan 24, 2025

The code I referenced was mostly related to p5.js (and game related), which is why it’s polling against the animation frame. But yeah, for Strudel, it makes more sense to handle the polling inside the signal.

That might also be connected to the fact that some button signals were only recognized after adding .segment().

// Add these lines to enable buttons(but why?)
$:pad.D.segment(16).gain(0)
$:pad.R.segment(16).gain(0)
$:pad.A.segment(16).gain(0)

nkymut and others added 9 commits January 26, 2025 02:04
- Replace requestAnimationFrame polling with signal
- individual signals for buttons and axes from baseSignal
- Remove window message-based gamepad state handling for toggleButtons
- Add module-level state storage to keep button state across strudel code update
@felixroos
Copy link
Collaborator

i've tested again, this time all buttons seem to work as expected! I've changed the docs a bit to use mask instead of gain, which makes things more clearer + more performant, as they are not played when inactive.

@felixroos
Copy link
Collaborator

felixroos commented Jan 31, 2025

in theory, buttonMap would need to be configurable, for example, my controller doesnt match the naming, e.g. x = b etc. not sure if we need this in this PR yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants