commit 9272e0354f9d95a3108cf0bc374d7cb405efd31b
parent 5e980e1c2b4b22e82fc3765f20e234126a580340
Author: Massimo Siboldi <mdsiboldi@gmail.com>
Date: Wed, 7 Mar 2018 15:40:03 -0800
Add master volume and change individual tones to just having a "mix"
Diffstat:
8 files changed, 53 insertions(+), 16 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 CircleButton from '../CircleButton/';
import WaveTable from '../WaveTable/';
+import Volume from '../Volume/';
import Param from '../Param/';
import Wheel from '../Wheel/';
import './App.css';
@@ -98,6 +99,7 @@ class App extends Component {
super();
let initBeats = 4;
this.state = {
+ volume: 0.7,
bpm: 120,
beat: 0,
playing: false,
@@ -126,6 +128,12 @@ class App extends Component {
});
}
+ updateVolume = (newVol) => {
+ this.setState({
+ volume: newVol
+ });
+ }
+
editingWaveform = () => this.state.tones[this.state.editingToneIdx].waveform
activeTones = () => {
@@ -261,7 +269,7 @@ class App extends Component {
}
render() {
- const waves = this.state.tones.map((form, idx) => {
+ const tones = this.state.tones.map((form, idx) => {
return (
<WaveManager
activate={this.changeEditingTone.bind(this, idx)}
@@ -352,12 +360,17 @@ class App extends Component {
update={this.setBeats}
/>
<Adsr adsr={this.state.adsr} update={this.updateAdsr} />
+ <Volume volume={this.state.volume} update={this.updateVolume} />
</div>
<div class="wave-manager-container">
- {waves}
+ {tones}
</div>
<button onClick={() => this.addTone()}>+</button>
- <Synth waveform={this.totalWaveform()} adsr={this.state.adsr}></Synth>
+ <Synth
+ waveform={this.totalWaveform()}
+ volume={this.state.volume}
+ adsr={this.state.adsr}
+ ></Synth>
</div>
);
}
diff --git a/src/Polyphonic.js b/src/Polyphonic.js
@@ -3,9 +3,16 @@ import Envelope from 'envelope-generator';
export default class Polyphonic {
constructor(audioContext) {
+ const masterVol = audioContext.createGain();
+ masterVol.gain.value = 0.7;
+ masterVol.connect(audioContext.destination);
this.voices = {};
this.audioContext = audioContext;
this.periodicWave = null;
+ this.masterVolume = masterVol;
+ }
+ setVolume(newVol) {
+ this.masterVolume.gain.value = newVol;
}
addVoice(note, adsr) {
this.voices[note.note] = this.voices[note.note] || [];
@@ -28,7 +35,7 @@ export default class Polyphonic {
envelope.connect(gain.gain);
osc.connect(gain);
- gain.connect(this.audioContext.destination);
+ gain.connect(this.masterVolume);
osc.start();
envelope.start(this.audioContext.currentTime - 0.1);
diff --git a/src/Synth/index.js b/src/Synth/index.js
@@ -26,6 +26,9 @@ export default class Synth extends Component {
}
componentWillReceiveProps(newProps) {
updateAudio(newProps.waveform);
+ if (newProps.volume !== this.props.volume) {
+ P.setVolume(newProps.volume);
+ }
}
render() {
return null;
@@ -34,11 +37,9 @@ export default class Synth extends Component {
function updateAudio(waveform) {
FFT.forward(waveform);
- //TODO: test what disableNormalization does. I'm guessing it allows me to have volume control, otherwise it would scale wave so max displacement is -1/1 instead of smaller val
const periodicWave = ac.createPeriodicWave(
new Float32Array(FFT.real),
- new Float32Array(FFT.imag),
- {disableNormalization: true}
+ new Float32Array(FFT.imag)
);
P.changeWave(periodicWave);
}
diff --git a/src/Volume/index.js b/src/Volume/index.js
@@ -2,11 +2,16 @@ import { h, Component } from 'preact';
import helpers from '../helpers';
import './style.css';
+const mapVol = (vol) => vol * vol;
+const unmapVol = (vol) => Math.sqrt(vol);
+
export default class Volume extends Component {
handleUpdate = (ev) => {
const minVolX = this.sliderRef.offsetLeft;
const maxVolX = this.sliderRef.offsetLeft + this.sliderRef.offsetWidth;
- this.props.update(helpers.bounded((ev.x - minVolX) / (maxVolX - minVolX), 0, 1));
+ const width = maxVolX - minVolX;
+ const offset = helpers.bounded(ev.x - minVolX, 0, width);
+ this.props.update(mapVol(offset / width));
}
componentDidMount() {
@@ -14,15 +19,18 @@ export default class Volume extends Component {
}
render() {
return (
- <div class="Volume" ref={(ref) => {this.volRef = ref}}>
- <span class="icon-volume"></span>
+ <div class={`Volume${this.props.class ? ' ' + this.props.class : ''}`} ref={(ref) => {this.volRef = ref}}>
+ {this.props.children.length
+ ? this.props.children
+ : (<span class="icon-volume"></span>)
+ }
<div
class="volume-triangle-container"
ref={(ref) => {this.sliderRef = ref}}
>
<div
class="volume-triangle -foreground"
- style={`transform: scale(${this.props.volume});`}
+ style={`transform: scale(${unmapVol(this.props.volume)});`}
></div>
<div class="volume-triangle -background"></div>
</div>
diff --git a/src/Volume/style.css b/src/Volume/style.css
@@ -19,6 +19,11 @@
}
.volume-triangle-container {
- display: inline-block;
+ display: inline-flex;
position: relative;
+ margin-left: 2px;
+}
+
+.Volume {
+ display: inline-flex;
}
diff --git a/src/WaveManager/index.js b/src/WaveManager/index.js
@@ -43,7 +43,10 @@ export default class WaveManager extends Component {
<Volume
volume={this.props.volume}
update={this.props.updateVolume}
- />
+ class="item"
+ >
+ <span>mix</span>
+ </Volume>
</div>
</div>
<div class="beats">
diff --git a/src/WaveManager/style.css b/src/WaveManager/style.css
@@ -27,6 +27,7 @@
margin: 0 5px;
cursor: pointer;
padding: 2px 5px;
+ font-size: 10pt;
}
.wave-manager .buttons .item:first-child {
@@ -43,10 +44,10 @@
background: none;
}
-.wave-manager .buttons .item {
+.wave-manager .buttons button.item {
opacity: 0.8;
}
-.wave-manager .buttons .item:hover {
+.wave-manager .buttons button.item:hover {
opacity: 1;
}
diff --git a/src/WaveTable/index.js b/src/WaveTable/index.js
@@ -33,7 +33,6 @@ export default class WaveTable extends Component {
}
if (this.props.resize) {
window.addEventListener('resize', (ev) => {
- console.log('yo', this.forceUpdate)
this.forceUpdate();
})
}