Last active
April 17, 2023 07:16
-
-
Save ronwnor/0249ab784918aabe164b82a9e1ad3a81 to your computer and use it in GitHub Desktop.
generate audio from functions!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| window.AudioContext = window.AudioContext || window.webkitAudioContext; | |
| const audioContext = new AudioContext(); | |
| const BuiltIn = require("core/math/builtin"); | |
| // returns the selected expression as a js function | |
| const parsedSelectedExpression = () => { | |
| // from the great fireflame | |
| const computeContext = () => { | |
| // Emulate what happens in the web worker | |
| const Context = require("core/math/context").Context, | |
| context = new Context(), | |
| changeSet = { | |
| isCompleteState: true, | |
| statements: {}, | |
| }; | |
| for (let stmt of Calc.controller.getAllItemModels()) { | |
| if (stmt.type !== "expression" && stmt.type !== "table") continue; | |
| changeSet.statements[stmt.id] = stmt; | |
| } | |
| context.processChangeSet(changeSet); | |
| context.updateAnalysis(); | |
| return context; | |
| } | |
| // get the selected expression from the computed thing | |
| let f = computeContext() | |
| .analysis[Calc.selectedExpressionId] | |
| .concreteTree | |
| .getCompiledFunction(); | |
| // replace _C[0], _C[1] stuff with the actual lists | |
| let src = f.source.replace(/_C\[(.*?)\]/g, e => '[' + f.constants[e.match(/\[(.*?)\]/)[1]] + ']'); | |
| // return it | |
| let parsedFunc; | |
| eval(`parsedFunc = (${f.args[0]}) => {${src}}`); | |
| return parsedFunc; | |
| } | |
| let isPlaying = false; // toggle | |
| let bufferSource; | |
| // generates the audio buffer? from the function | |
| const generateAudioFromExpression = () => { | |
| if(isPlaying){ | |
| bufferSource.stop(); | |
| isPlaying = false; | |
| return; | |
| } | |
| let parsedFunc = parsedSelectedExpression(); | |
| let bounds = Calc.graphpaperBounds.mathCoordinates; | |
| // audio part, from https://stackoverflow.com/a/34709510 | |
| let buf = new Float32Array(audioContext.sampleRate * (bounds.right - bounds.left)); | |
| for(let i=0; i<buf.length; i++){ | |
| buf[i] = parsedFunc((i/buf.length)*(bounds.right - bounds.left) + bounds.left); | |
| } | |
| let buffer = audioContext.createBuffer(1, buf.length, audioContext.sampleRate); | |
| buffer.copyToChannel(buf, 0) | |
| bufferSource = audioContext.createBufferSource(); | |
| bufferSource.buffer = buffer; | |
| bufferSource.connect(audioContext.destination); | |
| bufferSource.start(0); | |
| isPlaying = true; | |
| bufferSource.onended = () => isPlaying = false; | |
| } | |
| // divs and css and stuff | |
| const div = document.createElement('div'); | |
| div.innerText = "音"; | |
| div.style = ` | |
| position: absolute; | |
| bottom: 0; | |
| right: -1px; | |
| padding: 20px 7px 6px 20px; | |
| z-index: 3; | |
| cursor: pointer; | |
| text-align: left; | |
| opacity: 0.4; | |
| font-size: 115%; | |
| font-weight: bold; | |
| `; | |
| div.onmousedown = () => | |
| div.style.opacity = 1; | |
| div.onmouseup = () => { | |
| div.style.opacity = .8; | |
| generateAudioFromExpression(); | |
| } | |
| div.onmouseenter = () => { | |
| div.style.opacity = .8; | |
| } | |
| div.onmouseleave = () => { | |
| div.style.opacity = .2; | |
| } | |
| Calc.controller.dispatcher.register(() => { | |
| if(Calc.controller.focusLocation?.type == 'expression') | |
| document | |
| .querySelector(`div[expr-id="${Calc.controller.focusLocation.id}"] div.dcg-top-level-icon`) | |
| .append(div); | |
| }); | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
goddamn this is broken now