20
\$\begingroup\$

The sound of the theremin has been immortalized in The Beach Boys song Good Vibrations. Many also associate its sound with the theme for the original series of Star Trek, though apparently it was a soprano's emulation.

This challenge requires you to implement a theremin.

Input

  • Take 2 dimensional input from a mouse or other input device (e.g. you could use a joystick), which will produce a tone from an audio output device as follows:
    • increasing x will increase the frequency of the tone. Note that frequency increases exponentially with musical note, so you must implement a linear relationship between mouse x position and the musical note, and
    • increasing y will increase the volume of the tone.
  • There appears to be confusion regarding the waveform produced by a real theremin, so for simplicity, a sine wave (or close approximation thereof) must be used.

Rules

  • The tone produced must have at least a 2-octave range. More range is acceptable. A-440 must lie within the range.
  • In order to create the audible appearance of continuously variable frequency and amplitude, the range of values considered in both dimensions from the input device must be at least 500 Implementations may open a window (at least 500x500 pixels) to read input from mouse cursor position. Or without opening a window, coordinates may be read directly from the mouse or other input device.
  • There must be a simple means to stop the program - key-combination, mouse-click or other common input device. CTRL-c is sufficient.
  • Any standard libraries may be used, as long as they do not totally implement the solution with no other work required.
  • Standard rules for Code Golf and I/O
  • You may stop by having the mouse or input device lose focus on the input box.

Notes

  • Because the output tone is dynamically-generated, care must be take to ensure the tone is a continuous waveform; that is there are no audible clicks or pops caused by sudden changes of phase or amplitude.
  • You may limit the input size zone to 500 by 500 but it may be bigger.

This is , so the shortest answer in any language wins.

Special thanks

Special thanks to Digital Trauma for making this challenge and posting it in the Secret Santa's Sandbox. I have made a few edits and here is the original post.

\$\endgroup\$
10
\$\begingroup\$

JavaScript ES6, 215 188 bytes

This seems to work well in Chrome and Edge. Firefox and Safari not so much.

with(new AudioContext)o=createOscillator(onmousemove=e=>{o.frequency.value=9/innerWidth*e.x**2,v.gain.value=1-e.y/innerHeight}),v=createGain(),v.connect(destination),o.start(),o.connect(v)

Saved 27 bytes thanks to @darrylyeo

Try it online!

with(new AudioContext)o=createOscillator(onmousemove=e=>{o.frequency.value=9/innerWidth*e.x**2,v.gain.value=1-e.y/innerHeight}),v=createGain(),v.connect(destination),o.start(),o.connect(v)
<button onClick="o.stop()">Stop</button>

\$\endgroup\$
  • 1
    \$\begingroup\$ That is pretty good! I had way too much fun \$\endgroup\$ – Christopher Mar 30 '17 at 22:34
  • 2
    \$\begingroup\$ Thanks. I think it's even more fun with a with a square wave \$\endgroup\$ – powelles Mar 31 '17 at 0:08
  • 1
    \$\begingroup\$ Trying it out and about lost an eardrum \$\endgroup\$ – Christopher Mar 31 '17 at 0:18
  • \$\begingroup\$ o.type='sine' is unnecessary since it's the default. You can simplify document.onmousemove to just onmousemove. \$\endgroup\$ – darrylyeo Mar 31 '17 at 2:22
  • \$\begingroup\$ Golfed from 215 to 188 bytes: with(new AudioContext)o=createOscillator(onmousemove=e=>{o.frequency.value=9/innerWidth*e.x**2,v.gain.value=1-e.y/innerHeight}),v=createGain(),v.connect(destination),o.start(),o.connect(v) \$\endgroup\$ – darrylyeo Mar 31 '17 at 2:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.