commit f41c795a4b6ffd91a5440f19cbb51ad3f71170f6
parent fe7c8df2a07849953cb08d8ebcc06d78db248dfa
Author: Massimo Siboldi <mdsiboldi@gmail.com>
Date: Sat, 9 Dec 2017 17:07:10 -0800
Add adsr interface and knobs, no design
Diffstat:
5 files changed, 80 insertions(+), 21 deletions(-)
diff --git a/src/App/index.js b/src/App/index.js
@@ -4,6 +4,7 @@ import WaveManager from '../WaveManager/';
import Synth from '../Synth/';
import './App.css';
import consts from '../consts.js';
+import helpers from '../helpers.js';
const initialWave = new Array(consts.BUF_SIZE).fill(0);
@@ -42,6 +43,48 @@ const boolArray = {
}
}
+//TODO this
+class Knob extends Component {
+ componentDidMount() {
+ const handleMove = (ev) => {
+ let step = this.props.step || 0.5;
+ let newVal = this.props.val - (ev.movementY * step);
+ if (typeof(this.props.minVal) === 'number' && (newVal < this.props.minVal)) {
+ newVal = this.props.minVal;
+ } else if (typeof(this.props.maxVal) === 'number' && (newVal > this.props.maxVal)) {
+ newVal = this.props.maxVal;
+ }
+ this.props.update(newVal);
+ }
+ this.knobRef.addEventListener('mousedown', (ev) => {
+ ev.preventDefault();
+ document.addEventListener('mousemove', handleMove);
+ helpers.oneTime(document, 'mouseup', (ev) => {
+ document.removeEventListener('mousemove', handleMove);
+ });
+ })
+ }
+ render() {
+ return (
+ <div ref={(knob) => {this.knobRef = knob}}>{this.props.val}</div>
+ )
+ }
+}
+
+
+const Adsr = (props) => (
+ <div>
+ {['a', 'd', 's', 'r'].map((letter) => (
+ <Knob
+ val={props.adsr[letter]}
+ minVal={0}
+ maxVal={3}
+ step={0.1}
+ update={(newVal) => {props.update(letter, newVal)}}
+ />
+ ))}
+ </div>
+)
class App extends Component {
@@ -62,14 +105,20 @@ class App extends Component {
pos: {x: 0, y: 0}
},
adsr: {
- attackTime: 0.1,
- decayTime: 1,
- sustainLevel: 0.4,
- releaseTime: 2
+ a: 0.3,
+ d: 1,
+ s: 0.4,
+ r: 1
}
}
}
+ updateAdsr = (letter, val) => {
+ this.setState({
+ adsr: Object.assign({}, this.state.adsr, {[letter]: val})
+ });
+ }
+
editingWaveform = () => this.state.waveforms[this.state.editingWaveformIdx].waveform
activeWaveforms = () => this.state.waveforms.reduce((accum, val) => {
@@ -151,7 +200,6 @@ class App extends Component {
beats={this.state.waveforms[idx].beats}
beat={this.state.beat}
updateBeat={(i, val) => {
- console.log('updating', i, val);
this.updateWaveform(idx, {
beats: boolArray.update(
this.state.waveforms[idx].beats,
@@ -174,6 +222,7 @@ class App extends Component {
this.updateWaveform(this.state.editingWaveformIdx, {waveform});
}}
></WaveEditor>
+ <Adsr adsr={this.state.adsr} update={this.updateAdsr} />
<button onClick={() => {this.setBeats(this.state.numBeats + 1)}}>+ beat</button>
<button onClick={() => {this.setBeats(this.state.numBeats - 1)}}>- beat</button>
<button onClick={() => this.addWaveform()}>+</button>
diff --git a/src/Polyphonic.js b/src/Polyphonic.js
@@ -3,14 +3,18 @@ import Envelope from 'envelope-generator';
export default class Polyphonic {
constructor(audioContext) {
- this.voices = [];
this.audioContext = audioContext;
this.periodicWave = null;
}
addVoice(note, adsr) {
let osc = this.audioContext.createOscillator();
let gain = this.audioContext.createGain();
- let envelope = new Envelope(this.audioContext, adsr);
+ let envelope = new Envelope(this.audioContext, {
+ attackTime: adsr.a,
+ decayTime: adsr.d,
+ sustainTime: adsr.s,
+ releaseTime: adsr.r
+ });
osc.frequency.value = note.frequency;
gain.gain.setValueAtTime(0, 0)
if (this.periodicWave) {
diff --git a/src/WaveEditor/index.js b/src/WaveEditor/index.js
@@ -38,20 +38,19 @@ export default class waveEditor extends Component {
componentDidMount() {
drawArea(this.props.waveform, this.canvasRef);
const handleMove = (ev) => {
+ console.log('handling move');
this.updateWaveform({
- x: ev.x,
- y: ev.y
+ x: ev.x + window.scrollX,
+ y: ev.y + window.scrollY
}, this.props.waveform);
}
- document.addEventListener('mousedown', (ev) => {
- if (ev.target === this.canvasRef) {
- document.addEventListener('mousemove', handleMove);
- }
- });
- document.addEventListener('mouseup', (ev) => {
- document.removeEventListener('mousemove', handleMove);
- this.setState({
- prevZone: null
+ this.canvasRef.addEventListener('mousedown', (ev) => {
+ document.addEventListener('mousemove', handleMove);
+ helpers.oneTime(document, 'mouseup', (ev) => {
+ document.removeEventListener('mousemove', handleMove);
+ this.setState({
+ prevZone: null
+ });
});
});
}
diff --git a/src/WaveManager/index.js b/src/WaveManager/index.js
@@ -1,8 +1,7 @@
-import { h, Component} from 'preact';
+import { h, Component } from 'preact';
export default class WaveManager extends Component {
render() {
- console.log(this.props.beats);
return (
<div class="wave-manager">
<div class="buttons">
diff --git a/src/helpers.js b/src/helpers.js
@@ -2,5 +2,13 @@ export default {
linear: (m, x, b) => (m * x) + b,
bounded: (val, min, max) => val < min ? min : (val > max ? max : val),
scale: (buf, amt) => buf.map(val => val * amt),
- add: (arr1, arr2) => arr1.map((v, i) => v + arr2[i])
+ add: (arr1, arr2) => arr1.map((v, i) => v + arr2[i]),
+ oneTime: (target, type, handler) => {
+ const doOnce = (ev) => {
+ target.removeEventListener(type, doOnce);
+ handler(ev);
+ }
+ target.addEventListener(type, doOnce);
+ }
+
};