Skip to content

Commit

Permalink
Merge pull request #7 from MymmiJ/develop
Browse files Browse the repository at this point in the history
Antethesizer: Fixes
  • Loading branch information
MymmiJ authored May 4, 2021
2 parents 20bc9a3 + b938de7 commit a2e1c18
Show file tree
Hide file tree
Showing 9 changed files with 399 additions and 132 deletions.
113 changes: 57 additions & 56 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,20 @@ const light_theme = createMuiTheme({
* - accessibility review (aria+contrast-focused)! 1
* - Make light theme look better (Note, passage colors)
* - Light/dark theme toggle
* - 'Regenerate all' button to force all notes to regenerate in a track
* - 'Regenerate all' button to force all notes to regenerate
* - Add help system to assist with all parts of the app
* Options Menu:
* - Overall direction (determine root note by increasing/decreasing from source)
* - just generally keep track of lower down things from higher up rather than trying to do things strictly hierarchically!
* - Allow/add multiple generators per pattern
* Synths:
* - Make attack/decay/sustain/release more formalized (i.e. specify sustain!) (& ensure that the values _are able to_ scale to the length of time)!
* - Import/export wavetables as JSON 1
* - Import wavetables as mathematical formulae* - can't be free text entry to be eval'ed!
* - Allow converting from ifft form to wavetable*
* - Use display to input back into wavetable*
* - Overall direction (determine root note by increasing/decreasing from source)
* - just generally keep track of things rather than trying to do things hierarchically!
* - Allow/add multiple generators per pattern
* - Allow composing synths together
* - Allow specifying chord bias
* - Allow distortion
* - Allow distortion in synths
* Sections:
* - Allow specifying the mood of subsections*
* - Allow inserting specfic runs of notes
Expand All @@ -89,27 +90,26 @@ const light_theme = createMuiTheme({
* - Allow starting section after delay of x notes
* - Allow sections to be played backwards
* Ornaments:
* - Chord control (max depth, depth probability/lock, etc.) 1
* - Arpeggios
* - Acciaccatura/trills etc.
* - Microtonal shifts
* - (more) vibrato/tremolo
* - Allow 'skipped' notes
* Rhythm:
* - drop in replacement for 'setTimeout' with greater accuracy https://stackoverflow.com/questions/196027/is-there-a-more-accurate-way-to-create-a-javascript-timer-than-settimeout
* - time signature
* - accents
* - change individual note lengths (use American quarter note system) 1
* - allow use of hemisemidemiquaver system
* - syncopation
* - Update global
* - time signature
* - accents
* - change individual note lengths (use American quarter note system) 1
* - allow use of hemisemidemiquaver system
* - syncopation
* Dynamics:
* - vary dynamics based on mood 1
* - vary dynamics based on time signature
* Motifs:
* - Enable inserting motifs to be repeated, consisting of smaller sections with interval changes & chords specified
* Generation:
* - Improve generation by using pickBiasLate to descend slowly 1
* - Improve generation by using pickBiasLate to descend slowly
* - Ensure that generation is always valid by checking octave against octavian 1
* - Allow user to force ending the passage on the root note
* - Improve generation by remembering _first_ root Note of series
* (e.g. for Passage, remember real rootNote into the children and use to modify generation)
Expand All @@ -125,19 +125,31 @@ const light_theme = createMuiTheme({
* - POST-BETA FEATURE
* - on pasting notes, locks the segment index and reverse engineers the tension/release patterns
* Code:
* - Refactor to generate sound controls from just one array 1
* - Bugfix: keep track of global state/BPM better
* - Refactor: global and local state, remove unnecessary local state in segments wherever possible
*
*/

/**
* Move to own config file
*/
const defaultGlobalOptions = {
bpm: 120
bpm: 120,
useGlobalBPM: true
}
// Config ends

const App = () => {
const [context,] = useState(new AudioContext());
const [oscillators, setOscillators] = useState([]);
const [customSynths, setCustomSynths] = useState([]);
const [additionalSoundControls, setSoundControls] = useState([]);
const [soundControls, setSoundControls] = useState([{
key: uuidv4(),
primary: true,
notes: [],
context: null,
synth: null,
...defaultGlobalOptions
}]);
const [globalOptions, setGlobalOptions] = useState(defaultGlobalOptions);
const synthControls = {
addCustomSynth: () => synth => setCustomSynths(prev => [...prev, synth]),
Expand All @@ -163,20 +175,22 @@ const App = () => {
notes: [],
context: null,
synth: null,
...defaultGlobalOptions,
addNewSoundControls
...defaultGlobalOptions
}]);
const addToAdditionalNotes = (key) => ({ value, context, synth, bpm }) => {
const addToAdditionalNotes = (key) => ({ value, context, synth, bpm, useGlobalBPM }) => {
setSoundControls(prev => prev.map(
soundControls => soundControls.key !== key ?
soundControls :
soundControls.useGlobalBPM && useGlobalBPM ?
{ ...soundControls, bpm } :
soundControls :
Object.assign(
{ ...soundControls },
{
notes: value(soundControls.notes),
context,
synth,
bpm
bpm,
useGlobalBPM
}
)
))
Expand All @@ -187,8 +201,8 @@ const App = () => {
const clearOscillators = () => setOscillators([]);
const playAdditionalNotes = () => {
clearOscillators();
console.log('playing additional:', additionalSoundControls)
additionalSoundControls.forEach(
console.log('playing additional:', soundControls)
soundControls.forEach(
({ notes, context, synth, bpm }, _, __) => {
if(notes && context && synth){
playNotes(notes.flat(), context, synth, bpm, replaceOscillator);
Expand All @@ -200,38 +214,25 @@ const App = () => {
return (
<ThemeProvider theme={dark_theme}>
<CssBaseline/>
<SoundControls
key='alpha-and-omega'
context={ context }
addNewSoundControls={ addNewSoundControls }
customSynths={ customSynths }
synthControls={ synthControls }
primary={ true }
clearOscillators={ clearOscillators }
useOscillator={ replaceOscillator }
addToAdditionalNotes={ () => {} }
playAdditionalNotes={ playAdditionalNotes }
setGlobalOption={ setGlobalOption }
globalOptions={ globalOptions }
/>
{
additionalSoundControls.length > 0 &&
additionalSoundControls.map(
desc =>
<SoundControls
key={ desc.key }
context={ context }
customSynths={ customSynths }
synthControls={ synthControls }
addNewSoundControls={ desc.addNewSoundControls }
clearOscillators={ clearOscillators }
useOscillator={ replaceOscillator }
addToAdditionalNotes={ addToAdditionalNotes(desc.key) }
primary={ desc.primary }
setGlobalOption={ setGlobalOption }
globalOptions={ globalOptions }
removeSelf={ () => removeSelf(desc.key) } />
)
soundControls.map(
desc =>
<SoundControls
key={ desc.key }
context={ context }
customSynths={ customSynths }
synthControls={ synthControls }
addNewSoundControls={ addNewSoundControls }
clearOscillators={ clearOscillators }
useOscillator={ replaceOscillator }
addToAdditionalNotes={ addToAdditionalNotes(desc.key) }
playAdditionalNotes={ playAdditionalNotes }
primary={ desc.primary }
useGlobalBPM={ desc.useGlobalBPM }
setGlobalOption={ setGlobalOption }
globalOptions={ globalOptions }
removeSelf={ () => removeSelf(desc.key) } />
)
}
<Oscilloscope context={ context } source={ oscillators[oscillators.length-1] }/>
</ThemeProvider>
Expand Down
27 changes: 21 additions & 6 deletions src/music/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ const playNotes = (notes, context, synth, bpm, useOscillator=()=>{}) => {
// Note helpers ends

//Config to go in own file
const soundControlsShouldUpdateOn = ['bpm'];

const soundControlsShouldUpdateOn = ['bpm', 'useGlobalBPM'];
// Config ends

const SoundControls = ({
Expand Down Expand Up @@ -75,7 +74,7 @@ const SoundControls = ({
));
}

const { bpm } = deFactoOptions;
const { bpm, useGlobalBPM } = deFactoOptions;
const soundControlValues = soundControlsShouldUpdateOn.reduce((acc, curr) => {
acc[curr] = deFactoOptions[curr];
return acc;
Expand All @@ -87,12 +86,12 @@ const SoundControls = ({
}

const handleSetNotes = value => {
addToAdditionalNotes({ value, context, synth, bpm });
addToAdditionalNotes({ value, context, synth, bpm, useGlobalBPM });
setNotes( value );
}

const handleSetSynth = value => {
addToAdditionalNotes({ value: id=>id, context, synth: value, bpm });
addToAdditionalNotes({ value: id=>id, context, synth: value, bpm, useGlobalBPM });
setSynth( value );
}

Expand All @@ -111,9 +110,23 @@ const SoundControls = ({
}
setDeFactoOption(key, value);
}
const setDefactoOptions = (opts) => {
const updateObject = Object.entries(opts).reduce((acc, [key, value]) => {
setDeFactoOption(key, value);
if(soundControlsShouldUpdateOn.includes(key)) {
return Object.assign(acc, { [key]: value });
}
return acc;
}, {
value: id=>id,
context,
synth,
...soundControlValues
});
addToAdditionalNotes(updateObject);
}

const handlePlayAll = () => {
handlePlay();
playAdditionalNotes();
}

Expand All @@ -139,9 +152,11 @@ const SoundControls = ({
synthControls={ synthControls }
globalOptions={ globalOptions }
setGlobalOption={ setGlobalOption }
useGlobalBPM={ useGlobalBPM }
localOptions={ localOptions }
setLocalOption={ setLocalOption }
setDeFactoOption={ handleSetDeFactoOption }
setDeFactoOptions={ setDefactoOptions }
addNewSoundControls={ addNewSoundControls }
/>
</Grid>
Expand Down
16 changes: 9 additions & 7 deletions src/music/options/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ import {
FormControlLabel,
Switch
} from '@material-ui/core';
import React, { useState } from 'react';
import React from 'react';

const Option = ({ global, setGlobal, setOpt, Type, tooltipDetails, options=false, setLocal, local, ...props }) => {
const [useGlobal, setUseGlobal] = useState(true);
const Option = ({
global, setGlobal,
useGlobal, setUseGlobal,
setLocal, local,
setOpt,
Type, tooltipDetails, options=false,
...props }) => {
const value = useGlobal ? global : local;
const nextValue = useGlobal ? local : global;
const setValue = useGlobal ? setGlobal : setLocal;
Expand Down Expand Up @@ -42,10 +47,7 @@ const Option = ({ global, setGlobal, setOpt, Type, tooltipDetails, options=false
control={
<Switch
checked={useGlobal}
onChange={() => {
setUseGlobal(prev => !prev)
setOpt({ target: { value: nextValue }});
}}
onChange={setUseGlobal(nextValue, !useGlobal)}
name="useGlobal"
color="primary"
/>
Expand Down
9 changes: 8 additions & 1 deletion src/music/options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ const OptionMenu = ({
setDefaultRootNote,
globalOptions,
setGlobalOption,
useGlobalBPM,
localOptions,
setLocalOption,
setOpt
setOpt,
setOpts
}) => {
const [ customSynthOpen, setCustomSynthOpen ] = useState(false);
const [ synthMethodReplace, setSynthMethodReplace ] = useState(false);
Expand Down Expand Up @@ -252,6 +254,11 @@ const OptionMenu = ({
Type={ TextField }
global={ bpm }
setGlobal={ setGlobalOption('bpm') }
useGlobal={ useGlobalBPM }
setUseGlobal={ (next, useGlobalBPM) => () => setOpts({
bpm: next,
useGlobalBPM
}) }
tooltipDetails={{ placement: 'top', title: 'Beats Per Minute', label: 'BPM:', aria_label: 'beats per minute' }}
setLocal={ setLocalOption('bpm') } local={ localBPM } type={ 'number' }
setOpt={ setOpt('bpm') }/>
Expand Down
Loading

0 comments on commit a2e1c18

Please sign in to comment.