├── README.md ├── algos.js ├── fieldsos.css ├── index.html ├── patches.js └── util.js /README.md: -------------------------------------------------------------------------------- 1 | # FieldsOS 2 | 3 | Recreating my FieldsOS electronic music system for the web. 4 | 5 | Latest version deployed here: https://williamfields.com/fieldsos 6 | -------------------------------------------------------------------------------- /algos.js: -------------------------------------------------------------------------------- 1 | 2 | function algoRandom() 3 | { 4 | if (bdSelected) 5 | { 6 | bd.decay = randInt(1,100); 7 | bd.density = randInt(0,100); 8 | bd.frequency = randInt(20,200); 9 | bd.multi = randInt(1,16); 10 | bd.octaves = randInt(0,8); 11 | bd.pitchDecay = randInt(0,100); 12 | bd.random = randInt(0,100); 13 | bd.seq = getTunedSequence(); 14 | bd.steps = randInt(1,16); 15 | } 16 | 17 | if (hatSelected) 18 | { 19 | hat.decay = randInt(1,100); 20 | hat.density = randInt(0,100); 21 | hat.frequency = randInt(0,10000); 22 | hat.harmonicity = randInt(0,128); 23 | hat.modulationIndex = randInt(0,256); 24 | hat.multi = randInt(1,16); 25 | hat.random = randInt(0,100); 26 | hat.resonance = randInt(0,10000); 27 | hat.seq = getTunedSequence(); 28 | hat.steps = randInt(1,16); 29 | } 30 | 31 | if (snrSelected) 32 | { 33 | snr.decay = randInt(1,100); 34 | snr.density = randInt(0,100); 35 | snr.frequency = 100+Math.pow(Math.random(),2)*1000; 36 | snr.multi = randInt(1,16); 37 | snr.octaves = Math.pow(Math.random(),2)*8; 38 | snr.pitchDecay = randInt(0,100); 39 | snr.random = randInt(0,100); 40 | snr.seq = getTunedSequence(); 41 | snr.steps = randInt(1,16); 42 | if (probDo(0.33)) 43 | { 44 | snr.noiseType = "white"; 45 | } 46 | else 47 | { 48 | if (probDo(0.5)) 49 | { 50 | snr.noiseType = "pink"; 51 | } 52 | else 53 | { 54 | snr.noiseType = "brown"; 55 | } 56 | } 57 | } 58 | } 59 | 60 | 61 | function algoHiphop() 62 | { 63 | algoRandom(); 64 | 65 | if (bdSelected) 66 | { 67 | for (var i=0;i<16;i++) 68 | { 69 | bd.seq[i] = probDo(0.25) ? rand() : 0; 70 | } 71 | bd.seq[0] = 1; 72 | bd.decay = Math.pow(Math.random(),0.5)*100; 73 | bd.density = 100; 74 | bd.frequency = randInt(20,100); 75 | bd.multi = 8; 76 | bd.octaves = randInt(0,4); 77 | bd.pitchDecay = randInt(0,100); 78 | bd.random = randInt(0,25); 79 | bd.steps = 16; 80 | } 81 | 82 | if (hatSelected) 83 | { 84 | hat.decay = Math.pow(Math.random(),2)*100; 85 | hat.density = 100; 86 | hat.multi = probDo(0.5) ? 4 : 8; 87 | if (probDo(0.25)) // Sometimes do triplet hats 88 | { 89 | hat.multi = 12; 90 | } 91 | hat.random = randInt(0,25); 92 | hat.steps = 16; 93 | if (probDo(0.5)) // Constant hi-hats 94 | { 95 | hat.steps = 1; 96 | hat.seq[0] = 1; 97 | } 98 | } 99 | 100 | if (snrSelected) 101 | { 102 | for (var i=0;i<16;i++) // SNR always on the 2 and 4 103 | { 104 | snr.seq[i] = probDo(0.25) ? Math.pow(rand(),2) : 0; 105 | } 106 | snr.seq[4] = 1; 107 | snr.seq[12] = 1; 108 | snr.decay = Math.pow(Math.random(),0.5)*100; 109 | snr.density = 100; 110 | snr.multi = 8; 111 | snr.pitchDecay = randInt(0,100); 112 | snr.random = randInt(0,25); 113 | snr.steps = 16; 114 | } 115 | } 116 | 117 | 118 | function algoTechno() 119 | { 120 | algoRandom(); 121 | 122 | if (bdSelected) 123 | { 124 | bd.seq = [1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0]; 125 | bd.steps = 16; 126 | bd.multi = 8; 127 | bd.random = randInt(0,25); 128 | bd.density = 100; 129 | bd.pitchDecay = randInt(0,100); 130 | } 131 | 132 | if (hatSelected) 133 | { 134 | hat.steps = 16; 135 | if (probDo(0.5)) // Constant hi-hats 136 | { 137 | hat.steps = 1; 138 | hat.seq[0] = 1; 139 | } 140 | hat.multi = probDo(0.5) ? 4 : 8; 141 | hat.density = 100; 142 | hat.random = randInt(0,25); 143 | } 144 | 145 | if (snrSelected) 146 | { 147 | snr.pitchDecay = randInt(0,100); 148 | snr.steps = 16; 149 | snr.multi = probDo(0.5) ? 4 : 8; 150 | snr.density = 100; 151 | snr.random = randInt(0,25); 152 | } 153 | } -------------------------------------------------------------------------------- /fieldsos.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bgcolor: rgb(135, 158, 187); 3 | } 4 | 5 | body { 6 | background-color: var(--bgcolor); 7 | font-size: 1.5em; 8 | font-family: monospace; 9 | overflow-x: hidden; 10 | } 11 | 12 | .container { 13 | position: absolute; 14 | top: 50%; 15 | transform: translate(-50%, -50%); 16 | left: 50%; 17 | width: 100%; 18 | text-align: center; 19 | max-width: 500px; 20 | } 21 | 22 | .buttonContainer { 23 | margin: 25px; 24 | white-space: nowrap; 25 | } 26 | 27 | 28 | .algoSelector { 29 | font-family: monospace; 30 | font-size: 1em; 31 | margin:10px; 32 | background-color: rgba(0, 0, 0, 0); 33 | border: 2px solid black; 34 | padding:5px; 35 | } 36 | 37 | .valueDisplay { 38 | display: inline-block; 39 | width: 40px; 40 | margin-left: 10px; 41 | } 42 | 43 | .sliderContainer { 44 | margin-top: 25px; 45 | white-space: nowrap; 46 | } 47 | 48 | .slider { 49 | width: 100%; 50 | max-width:50%; 51 | } 52 | 53 | input[type=range] { 54 | height: 1em; 55 | appearance: none; 56 | } 57 | 58 | input[type=range]:focus { 59 | outline: none; 60 | } 61 | 62 | input[type=range]::-webkit-slider-thumb { 63 | height: 25px; 64 | width: 15px; 65 | background: black; 66 | appearance: none; 67 | } 68 | 69 | input[type=range]::-webkit-slider-runnable-track { 70 | background: var(--bgcolor); 71 | border: 2px solid #000000; 72 | } 73 | 74 | .sliderLabel { 75 | width: 100px; 76 | text-align:right; 77 | float:left; 78 | margin-right: 10px; 79 | } 80 | 81 | 82 | 83 | .controlButton { 84 | font-family:monospace; 85 | font-size: 50px; 86 | background-color: rgba(0, 0, 0, 0); 87 | margin: 0px 10px; 88 | padding: 10px 25px; 89 | } 90 | 91 | .checkboxContainer { 92 | width: 390px; 93 | margin: 50px 100px; 94 | text-align: center; 95 | } 96 | 97 | /* Customize the label (the container) */ 98 | .checkbox { 99 | display: block; 100 | position: relative; 101 | float: left; 102 | padding-left: 70px; 103 | text-align:left; 104 | cursor: pointer; 105 | width:60px; 106 | -webkit-user-select: none; 107 | -moz-user-select: none; 108 | -ms-user-select: none; 109 | user-select: none; 110 | } 111 | 112 | /* Hide the browser's default checkbox */ 113 | .checkbox input { 114 | position: absolute; 115 | opacity: 0; 116 | cursor: pointer; 117 | height: 0; 118 | width: 0; 119 | } 120 | 121 | /* Create a custom checkbox */ 122 | .checkmark { 123 | position: absolute; 124 | top: 0; 125 | left: 0; 126 | height: 50px; 127 | width: 50px; 128 | background-color: rgba(0, 0, 0, 0); 129 | border: 2px solid black; 130 | } 131 | 132 | /* When the checkbox is checked, add a black background */ 133 | .checkbox input:checked ~ .checkmark { 134 | background-color: black; 135 | } 136 | 137 | .checkboxLabel 138 | { 139 | margin-top:15px; 140 | } 141 | 142 | 143 | .disable-select{ 144 | user-select:none; 145 | -moz-user-select:none; 146 | -webkit-user-select:none; 147 | -webkit-touch-callout:none; 148 | -ms-user-select:none; 149 | } 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |