@audiofab-io/easy-spin-ui 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/styles.css
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
`&&this.pos<this.source.length;)this.advance();else n===`
|
|
5
5
|
`?(e.push({type:t.NEWLINE,value:`
|
|
6
6
|
`,line:this.line,column:this.column}),this.advance()):n===`,`?(e.push({type:t.COMMA,value:`,`,line:this.line,column:this.column}),this.advance()):n===`:`?(e.push({type:t.COLON,value:`:`,line:this.line,column:this.column}),this.advance()):n===`(`?(e.push({type:t.LPAREN,value:`(`,line:this.line,column:this.column}),this.advance()):n===`)`?(e.push({type:t.RPAREN,value:`)`,line:this.line,column:this.column}),this.advance()):/[a-zA-Z_]/.test(n)?e.push(this.readIdentifier()):/[0-9.]/.test(n)||n===`$`||n===`%`?e.push(this.readNumber()):/[-+*/|&<>^!]/.test(n)?e.push({type:t.OPERATOR,value:this.advance(),line:this.line,column:this.column}):this.advance()}return e.push({type:t.EOF,value:``,line:this.line,column:this.column}),e}readIdentifier(){let e=``,n=this.line,r=this.column;for(;/[a-zA-Z0-9_#^.]/.test(this.peek());)e+=this.advance();let i=e.toUpperCase();return[`EQU`,`MEM`].includes(i)?{type:t.DIRECTIVE,value:i,line:n,column:r}:{type:t.IDENTIFIER,value:i,line:n,column:r}}readNumber(){let e=``,n=this.line,r=this.column;if(this.peek()===`$`)for(e+=this.advance();/[0-9a-fA-F]/.test(this.peek());)e+=this.advance();else if(this.peek()===`%`)for(e+=this.advance();/[01_]/.test(this.peek());)e+=this.advance();else if(this.peek()===`0`&&(this.source[this.pos+1]||``).toLowerCase()===`x`)for(e+=this.advance(),e+=this.advance();/[0-9a-fA-F]/.test(this.peek());)e+=this.advance();else for(;/[0-9\.]/.test(this.peek());)e+=this.advance();return{type:t.NUMBER,value:e,line:n,column:r}}},r=class{constructor(e){this.pos=0,this.tokens=e.filter((n,r)=>n.type!==t.NEWLINE||this.isNextSignificant(e,r))}isNextSignificant(e,n){for(let r=n+1;r<e.length;r++)if(e[r].type!==t.NEWLINE)return e[r].type!==t.EOF;return!1}peek(){return this.tokens[this.pos]||{type:t.EOF,value:``,line:-1,column:-1}}advance(){return this.tokens[this.pos++]}match(e){return this.peek().type===e?this.advance():null}parse(){let e=[];for(;this.peek().type!==t.EOF;){let n=this.parseStatement();for(n&&e.push(n);this.match(t.NEWLINE););}return e}parseStatement(){let n=this.peek();if(n.type===t.IDENTIFIER){let e=this.tokens[this.pos+1];if(e&&e.type===t.COLON){let e=this.advance();return this.advance(),{type:`Label`,name:e.value,line:e.line}}if(e&&e.type===t.DIRECTIVE){let e=this.advance(),t=this.advance(),n=this.parseExpression();return{type:`Directive`,name:t.value,identifier:e.value,expression:n,line:t.line}}}if(n.type===t.DIRECTIVE){let n=this.advance(),r=this.match(t.IDENTIFIER);if(!r)throw new e(`Expected identifier after ${n.value}`,n.line,n.column);let i=this.parseExpression();return{type:`Directive`,name:n.value,identifier:r.value,expression:i,line:n.line}}if(n.type===t.IDENTIFIER){let e=this.advance(),n=[];if(this.peek().type!==t.NEWLINE&&this.peek().type!==t.EOF)for(n.push(this.parseExpression());this.match(t.COMMA);)n.push(this.parseExpression());return{type:`Instruction`,mnemonic:e.value,operands:n,line:e.line}}return this.advance(),null}parseExpression(){return this.parseBitwise()}parseBitwise(){let e=this.parseShift();for(;this.peek().type===t.OPERATOR&&[`|`,`&`,`^`].includes(this.peek().value);){let t=this.advance().value,n=this.parseShift();e={type:`Binary`,left:e,operator:t,right:n}}return e}parseShift(){let e=this.parseAdditive();for(;this.peek().type===t.OPERATOR&&[`<`,`>`].includes(this.peek().value);){let t=this.advance().value,n=this.parseAdditive();e={type:`Binary`,left:e,operator:t,right:n}}return e}parseAdditive(){let e=this.parseMultiplicative();for(;this.peek().type===t.OPERATOR&&(this.peek().value===`+`||this.peek().value===`-`);){let t=this.advance().value,n=this.parseMultiplicative();e={type:`Binary`,left:e,operator:t,right:n}}return e}parseMultiplicative(){let e=this.parsePrimary();for(;this.peek().type===t.OPERATOR&&(this.peek().value===`*`||this.peek().value===`/`);){let t=this.advance().value,n=this.parsePrimary();e={type:`Binary`,left:e,operator:t,right:n}}return e}parsePrimary(){let n=this.peek();if(n.type===t.NUMBER)return{type:`Number`,value:this.parseNumberValue(this.advance().value)};if(n.type===t.IDENTIFIER)return{type:`Identifier`,name:this.advance().value};if(n.type===t.LPAREN){this.advance();let r=this.parseExpression();if(!this.match(t.RPAREN))throw new e(`Expected )`,n.line,n.column);return r}if(n.type===t.OPERATOR&&(n.value===`-`||n.value===`+`||n.value===`!`))return{type:`Unary`,operator:this.advance().value,expression:this.parsePrimary()};throw new e(`Unexpected token ${n.value}`,n.line,n.column)}parseNumberValue(e){let t=e.toUpperCase();return t.startsWith(`$`)?parseInt(e.slice(1),16):t.startsWith(`0X`)?parseInt(e,16):t.startsWith(`%`)?parseInt(e.slice(1).replace(/_/g,``),2):parseFloat(e)}},i={SOF:{opcode:13,fields:[{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`d`,bits:11,offset:5,type:`S_10`},{name:`op`,bits:5,offset:0,value:13}]},AND:{opcode:14,fields:[{name:`mask`,bits:24,offset:8,type:`U`},{name:`op`,bits:8,offset:0,value:14}]},OR:{opcode:15,fields:[{name:`mask`,bits:24,offset:8,type:`U`},{name:`op`,bits:8,offset:0,value:15}]},XOR:{opcode:16,fields:[{name:`mask`,bits:24,offset:8,type:`U`},{name:`op`,bits:8,offset:0,value:16}]},LOG:{opcode:11,fields:[{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`d`,bits:11,offset:5,type:`S4_6`},{name:`op`,bits:5,offset:0,value:11}]},EXP:{opcode:12,fields:[{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`d`,bits:11,offset:5,type:`S_10`},{name:`op`,bits:5,offset:0,value:12}]},SKP:{opcode:17,fields:[{name:`flags`,bits:5,offset:27,type:`LFO`},{name:`n`,bits:6,offset:21,type:`S`},{name:`op`,bits:5,offset:0,value:17}]},JMP:{opcode:17,fields:[{name:`flags`,bits:5,offset:27,value:0},{name:`n`,bits:6,offset:21,type:`S`},{name:`op`,bits:5,offset:0,value:17}]},NOP:{opcode:17,fields:[{name:`flags`,bits:5,offset:27,value:0},{name:`n`,bits:6,offset:21,value:0},{name:`op`,bits:5,offset:0,value:17}]},RDAX:{opcode:4,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:4}]},WRAX:{opcode:6,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:6}]},MAXX:{opcode:9,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:9}]},MULX:{opcode:10,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`op`,bits:5,offset:0,value:10}]},RDFX:{opcode:5,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:5}]},WRLX:{opcode:8,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:8}]},WRHX:{opcode:7,fields:[{name:`addr`,bits:6,offset:5,type:`REG`},{name:`coeff`,bits:16,offset:16,type:`S1_14`},{name:`op`,bits:5,offset:0,value:7}]},LDAX:{opcode:5,fields:[{name:`coeff`,bits:16,offset:16,value:0},{name:`addr`,bits:6,offset:5,type:`REG`},{name:`op`,bits:5,offset:0,value:5}]},RDA:{opcode:0,fields:[{name:`addr`,bits:16,offset:5,type:`ADDR`},{name:`coeff`,bits:11,offset:21,type:`S1_9`},{name:`op`,bits:5,offset:0,value:0}]},RMPA:{opcode:1,fields:[{name:`coeff`,bits:11,offset:21,type:`S1_9`},{name:`op`,bits:5,offset:0,value:1}]},WRA:{opcode:2,fields:[{name:`addr`,bits:16,offset:5,type:`ADDR`},{name:`coeff`,bits:11,offset:21,type:`S1_9`},{name:`op`,bits:5,offset:0,value:2}]},WRAP:{opcode:3,fields:[{name:`addr`,bits:16,offset:5,type:`ADDR`},{name:`coeff`,bits:11,offset:21,type:`S1_9`},{name:`op`,bits:5,offset:0,value:3}]},WLDS:{opcode:18,fields:[{name:`sinLfo`,bits:1,offset:29,type:`U`},{name:`freq`,bits:9,offset:20,type:`U`},{name:`ampl`,bits:15,offset:5,type:`U`},{name:`op`,bits:5,offset:0,value:18}]},WLDR:{opcode:18,fields:[{name:`type`,bits:1,offset:30,value:1},{name:`rmpLfo`,bits:1,offset:29,type:`U`},{name:`freq`,bits:16,offset:13,type:`U`},{name:`ampl`,bits:2,offset:5,type:`U`},{name:`op`,bits:5,offset:0,value:18}]},JAM:{opcode:19,fields:[{name:`rmpLfo`,bits:1,offset:6,type:`U`},{name:`type`,bits:1,offset:7,value:1},{name:`op`,bits:5,offset:0,value:19}]},CHO:{opcode:20,fields:[{name:`mode`,bits:2,offset:30,type:`U`},{name:`flags`,bits:6,offset:24,type:`U`},{name:`n`,bits:3,offset:21,type:`U`},{name:`param`,bits:16,offset:5,type:`ADDR`},{name:`op`,bits:5,offset:0,value:20}]},CLR:{opcode:14,fields:[{name:`val`,bits:32,offset:0,value:14}]},NOT:{opcode:16,fields:[{name:`val`,bits:32,offset:0,value:16}]},ABSA:{opcode:9,fields:[{name:`val`,bits:32,offset:0,value:9}]}},a=class{static encode(e,t){switch(e){case`S1_14`:return this.toFixedPoint(t,1,14,2);case`S_15`:return this.toFixedPoint(t,0,15,1);case`S1_9`:return this.toFixedPoint(t,1,9,2);case`S_10`:return this.toFixedPoint(t,0,10,1);case`S4_6`:return this.toFixedPoint(t,4,6,16)}return t}static toFixedPoint(e,t,n,r){let i=r/(1<<n),a=-r,o=r-i,s=Math.trunc(Math.min(Math.max(e,a),o)*(1<<n)),c=1+t+n,l=(1<<c)-1;return s<0?s+(1<<c)&l:s&l}static assembleInstruction(e,t,n){let r=0,i=0;for(let e of n.fields){let n=0;e.value===void 0?(n=t[i++],e.type&&(n=this.encode(e.type,n))):n=e.value;let a=e.bits===32?4294967295:(1<<e.bits)-1;r|=(n&a)<<e.offset}return r>>>0}},o=class{constructor(e={}){this.problems=[],this.symbols=new Map,this.memories=[],this.labels=new Map,this.addressToLineMap=new Map,this.usedRegisters=new Set,this.usedLFOs=new Set,this.configuredLFOs=new Set,this.userSymbols=new Set,this.symbolLines=new Map,this.PREDEFINED_SYMBOLS={SIN0_RATE:0,SIN0_RANGE:1,SIN1_RATE:2,SIN1_RANGE:3,RMP0_RATE:4,RMP0_RANGE:5,RMP1_RATE:6,RMP1_RANGE:7,POT0:16,POT1:17,POT2:18,ADCL:20,ADCR:21,DACL:22,DACR:23,ADDR_PTR:24,SIN0:0,SIN1:1,RMP0:2,RMP1:3,COS0:8,COS1:9,RDA:0,SOF:2,RDAL:3,SIN:0,COS:1,REG:2,COMPC:4,COMPA:8,RPTR2:16,NA:32,RUN:16,ZRC:8,ZRO:4,GEZ:2,NEG:1},this.reservedSymbols=new Set,this.options={fv1AsmMemBug:e.fv1AsmMemBug??!0,clampReals:e.clampReals??!0,regCount:e.regCount??32,progSize:e.progSize??128,delaySize:e.delaySize??32768},this.reset()}reset(){this.problems=[],this.symbols.clear(),this.memories=[],this.labels.clear(),this.addressToLineMap.clear(),this.usedRegisters.clear(),this.usedLFOs.clear(),this.configuredLFOs.clear(),this.userSymbols.clear(),this.symbolLines.clear(),this.initSymbols()}initSymbols(){for(let[e,t]of Object.entries(this.PREDEFINED_SYMBOLS))this.symbols.set(e,t),this.reservedSymbols.add(e);for(let e=0;e<this.options.regCount;e++)this.symbols.set(`REG${e}`,32+e),this.reservedSymbols.add(`REG${e}`)}assemble(t){this.reset();try{let e=new r(new n(t).tokenize()).parse();return this.pass1_ResolveDirectives(e),this.pass2_ResolveLabels(e),{machineCode:this.pass3_GenerateCode(e),problems:this.problems,labels:this.labels,symbols:Array.from(this.symbols.entries()).filter(([e])=>this.userSymbols.has(e)).map(([e,t])=>({name:e,value:t.toString(),line:this.symbolLines.get(e)})),memories:this.memories,addressToLineMap:this.addressToLineMap,usedRegistersCount:this.usedRegisters.size,usedLFOs:Array.from(this.usedLFOs)}}catch(t){let n=t instanceof e?t.line:1;return this.problems.push({message:`Parser error: ${t instanceof Error?t.message:String(t)}`,isfatal:!0,line:n}),{machineCode:[],problems:this.problems,labels:new Map,symbols:[],memories:[],addressToLineMap:new Map,usedRegistersCount:0,usedLFOs:[]}}}pass1_ResolveDirectives(e){let t=0;for(let n of e)if(n.type===`Directive`){if(n.name===`EQU`)if(this.reservedSymbols.has(n.identifier))this.problems.push({message:`Cannot redefine reserved symbol '${n.identifier}'`,isfatal:!0,line:n.line});else if(this.userSymbols.has(n.identifier))this.problems.push({message:`Symbol '${n.identifier}' is already defined on line ${this.symbolLines.get(n.identifier)}`,isfatal:!0,line:n.line});else{let e=this.evaluateExpression(n.expression,n.line);this.symbols.set(n.identifier,e),this.userSymbols.add(n.identifier),this.symbolLines.set(n.identifier,n.line)}else if(n.name===`MEM`){if(this.reservedSymbols.has(n.identifier)){this.problems.push({message:`Cannot redefine reserved symbol '${n.identifier}'`,isfatal:!0,line:n.line});continue}let e=this.evaluateExpression(n.expression,n.line),r=t,i=r+(e%2?(e-1)/2-1:e/2),a=r+e-1,o=a+ +!!this.options.fv1AsmMemBug,s={name:n.identifier,size:e,start:r,middle:i,end:a,line:n.line,original:``};this.memories.push(s),this.symbols.set(n.identifier,r),this.symbols.set(n.identifier+`^`,i),this.symbols.set(n.identifier+`#`,o),t=o+1}}}pass2_ResolveLabels(e){let t=0;for(let n of e)n.type===`Label`?this.labels.set(n.name,{line:n.line,instructionLine:t}):n.type===`Instruction`&&t++}pass3_GenerateCode(e){let t=[],n=0;for(let r of e)if(r.type===`Instruction`){let e=i[r.mnemonic];if(!e){this.problems.push({message:`Unknown instruction ${r.mnemonic}`,isfatal:!0,line:r.line}),t.push(0);continue}let o=r.operands.map(e=>e.type===`Identifier`&&this.labels.has(e.name)?this.labels.get(e.name).instructionLine-n-1:this.evaluateExpression(e,r.line));if(r.mnemonic===`WLDS`||r.mnemonic===`WLDR`){let e=o[0],t=this.getLFOName(e);t&&(r.mnemonic===`WLDS`&&(this.configuredLFOs.has(t)&&this.problems.push({message:`LFO ${t} is configured more than once`,isfatal:!0,line:r.line}),this.configuredLFOs.add(t)),this.usedLFOs.add(t))}if(r.mnemonic===`CHO`){let e=o[0],t=o[1],n=this.symbols.get(`RDA`),r=this.symbols.get(`SOF`);if(e===this.symbols.get(`RDAL`))o=[e,2,t,0];else if(e===n||e===r){let n=o[2],i=o[3];e===r&&(i=a.encode(`S1_14`,i)),o=[e,n,t,i]}}else if(r.mnemonic===`WLDR`){let e=o[2];switch(e){case 512:e=3;break;case 1024:e=2;break;case 2048:e=1;break;case 4096:e=0;break;default:this.problems.push({message:`Invalid amplitude ${e} for WLDR`,isfatal:!0,line:r.line})}let t=o[0];[0,2].includes(t)?t=0:[1,3].includes(t)&&(t=1),o=[t,o[1],e]}else if(r.mnemonic===`JAM`){let e=o[0];[0,2].includes(e)?e=0:[1,3].includes(e)&&(e=1),o=[e]}if(e.fields.forEach((e,t)=>{e.type===`REG`&&o[t]!==void 0&&this.trackRegister(o[t],r.line)}),r.mnemonic===`WRAX`||r.mnemonic===`RDAX`){let e=o[0],t=this.getLFONameFromRegister(e);t&&this.usedLFOs.add(t)}t.push(a.assembleInstruction(r.mnemonic,o,e)),this.addressToLineMap.set(n,r.line),n++}for(;t.length<this.options.progSize;)t.push(17);return t}trackRegister(e,t){if(e>=32&&e<=63){let n=e-32;n>=this.options.regCount&&this.problems.push({message:`Register REG${n} exceeds limit ${this.options.regCount}`,isfatal:!0,line:t}),this.usedRegisters.add(n)}}getLFOName(e){switch(e){case 0:return`SIN0`;case 1:return`SIN1`;case 2:return`RMP0`;case 3:return`RMP1`;default:return null}}getLFONameFromRegister(e){switch(e){case 0:case 1:return`SIN0`;case 2:case 3:return`SIN1`;case 4:case 5:return`RMP0`;case 6:case 7:return`RMP1`;default:return null}}evaluateExpression(e,t){switch(e.type){case`Number`:return e.value;case`Identifier`:return this.symbols.has(e.name)?this.symbols.get(e.name):(this.problems.push({message:`Undefined symbol ${e.name}`,isfatal:!0,line:t}),0);case`Binary`:let n=this.evaluateExpression(e.left,t),r=this.evaluateExpression(e.right,t);switch(e.operator){case`+`:return n+r;case`-`:return n-r;case`*`:return n*r;case`/`:return n/r;case`|`:return n|r;case`&`:return n&r;case`^`:return n^r;case`<`:return n<<r>>>0;case`>`:return n>>>r;default:return 0}case`Unary`:let i=this.evaluateExpression(e.expression,t);return e.operator===`-`?-i:e.operator===`!`?~Math.floor(i)>>>0:i}}static formatMachineCode(e){return e.map((e,t)=>`${t.toString().padStart(4,`0`)}\t${e.toString(16).toUpperCase().padStart(8,`0`)}`).join(`
|
|
7
|
-
`)}static toUint8Array(e){let t=new ArrayBuffer(e.length*4),n=new DataView(t);return e.forEach((e,t)=>n.setUint32(t*4,e,!1)),new Uint8Array(t)}static getMiddleAddr(e,t){return e+(t%2?(t-1)/2-1:t/2)}static getEndAddr(e,t,n){return e+t-1+ +!!n}},s=class e{constructor(){this.delaySize=32768,this.delayMask=32767,this.regCount=32,this.progSize=128,this.sin0=0,this.cos0=0,this.sin1=0,this.cos1=0,this.rmp0=0,this.rmp1=0,this.sin0_rate=0,this.sin0_range=0,this.sin1_rate=0,this.sin1_range=0,this.rmp0_rate=0,this.rmp0_range=0,this.rmp1_rate=0,this.rmp1_range=0,this.acc=0,this.pacc=0,this.lr=0,this.lfo=0,this.delayPointer=0,this.firstRun=!0,this.pc=0,this.breakpoints=new Set,this.symbols=[],this.memories=[],this.fv1AsmMemBug=!1,this.potSmoothCoeff=0,this.potSmoothed=[.5,.5,.5],this.potSmoothInit=!1,this.traceEnabled=!1,this.traceWriter=null,this.cycleCount=0,this.traceCycle=0,this.traceMaxCycles=0,this.traceRowCount=0,this.traceDelayAddr=-1,this.traceDelayOffset=-1,this.traceDelayOp=``,this.traceDelayValue=0,this.traceInstructionPC=-1,this.currentReadOffsets=new Set,this.traceOnComplete=null,this.delayRam=new Float32Array(this.delaySize),this.registers=new Float32Array(32+this.regCount),this.program=new Uint32Array(this.progSize)}setCapabilities(e,t,n){this.delaySize=e,this.delayMask=e-1,this.regCount=t,this.progSize=n,this.delayRam=new Float32Array(this.delaySize),this.registers=new Float32Array(32+this.regCount),this.program=new Uint32Array(this.progSize),this.reset()}getDelayPointer(){return this.delayPointer}getDelaySize(){return this.delaySize}loadProgram(e){e.length>this.progSize&&console.warn(`Program size (${e.length}) exceeds max size (${this.progSize}). Truncating.`),this.program.fill(0),this.program.set(e.slice(0,this.progSize)),this.reset()}reset(){this.delayRam.fill(0),this.registers.fill(0),this.acc=0,this.pacc=0,this.lr=0,this.lfo=0,this.pc=0,this.delayPointer=0,this.firstRun=!0,this.sin0=0,this.sin1=0,this.cos0=-1,this.cos1=-1,this.rmp0=0,this.rmp1=0,this.sin0_rate=0,this.sin0_range=0,this.sin1_rate=0,this.sin1_range=0,this.rmp0_rate=0,this.rmp0_range=0,this.rmp1_rate=0,this.rmp1_range=0,this.registers[16]=.5,this.registers[17]=.5,this.registers[18]=.5,this.potSmoothed[0]=.5,this.potSmoothed[1]=.5,this.potSmoothed[2]=.5,this.potSmoothInit=!1}setPotSmoothing(e,t){e<=0||t<=0?this.potSmoothCoeff=0:this.potSmoothCoeff=1-Math.exp(-1/(e*t))}setBreakpoints(e){this.breakpoints=e}setSymbols(e,t,n=!1){this.symbols=e,this.memories=t,this.fv1AsmMemBug=n}processBlock(e,t,n,r,i,a,o){let s=e.length;for(let c=0;c<s;c++){let[s,l]=this.step(e[c],t[c],i,a,o);n[c]=s,r[c]=l}}step(e,t,n,r,i,a=!1){this.pc===0&&this.beginFrame(e,t,n,r,i);let o=!0;for(;this.pc<this.progSize;){if(this.breakpoints.has(this.pc)&&(!o||!a))return[...this.getOutputs(),!0];this.stepInstruction(),o=!1}return[...this.endFrame(),!1]}getOutputs(){return[this.registers[22],this.registers[23]]}beginFrame(t=0,n=0,r=0,i=0,a=0){this.cycleCount++,this.currentReadOffsets.clear();let o=t=>Math.max(-1,Math.min(e.MAX_ACC,t)),s=e=>Math.floor(Math.max(0,Math.min(.9999999,e))*1024)/1024;this.acc=0,this.lr=0,this.pacc=0,this.pc=0,this.potSmoothCoeff>0&&(this.potSmoothInit?(this.potSmoothed[0]+=(r-this.potSmoothed[0])*this.potSmoothCoeff,this.potSmoothed[1]+=(i-this.potSmoothed[1])*this.potSmoothCoeff,this.potSmoothed[2]+=(a-this.potSmoothed[2])*this.potSmoothCoeff):(this.potSmoothed[0]=r,this.potSmoothed[1]=i,this.potSmoothed[2]=a,this.potSmoothInit=!0),r=this.potSmoothed[0],i=this.potSmoothed[1],a=this.potSmoothed[2]),this.registers[20]=o(t),this.registers[21]=o(n),this.registers[16]=s(r),this.registers[17]=s(i),this.registers[18]=s(a),this.updateStateRegisters()}endFrame(){return this.pc=0,this.firstRun=!1,this.updateLFOs(),this.updateStateRegisters(),this.advanceTraceCycle(),this.delayPointer=(this.delayPointer-1+this.delaySize)%this.delaySize,[this.registers[22],this.registers[23]]}stepInstruction(){if(this.pc>=this.progSize)return this.pc;let e=this.program[this.pc],t=e&31,n=this.acc;this.traceDelayAddr=-1,this.traceDelayOffset=-1,this.traceDelayOp=``,this.traceDelayValue=0,this.traceInstructionPC=this.pc;let r=this.executeInstruction(e);return this.traceEnabled&&this.logTrace(this.traceInstructionPC,t,e,n),t!==17&&(this.pacc=n),this.pc+=1+r,this.pc}executeInstruction(e){let t=e&31,n=0;switch(t){case 0:this.opRDA(e);break;case 1:this.opRMPA(e);break;case 2:this.opWRA(e);break;case 3:this.opWRAP(e);break;case 4:this.opRDAX(e);break;case 5:this.opRDFX(e);break;case 6:this.opWRAX(e);break;case 7:this.opWRHX(e);break;case 8:this.opWRLX(e);break;case 9:this.opMAXX(e);break;case 10:this.opMULX(e);break;case 11:this.opLOG(e);break;case 12:this.opEXP(e);break;case 13:this.opSOF(e);break;case 14:this.opAND(e);break;case 15:this.opOR(e);break;case 16:this.opXOR(e);break;case 17:n=this.opSKP(e);break;case 18:e>>>30&1?this.opWLDR(e):this.opWLDS(e);break;case 19:this.opJAM(e);break;case 20:this.opCHO(e);break;default:break}return n}opRDA(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask,i=this.delayRam[r];this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`R`,this.traceDelayValue=i,this.currentReadOffsets.add(t),this.lr=i,this.acc+=i*n,this.acc=this.saturate(this.acc)}opWRA(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask;this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`W`,this.traceDelayValue=this.acc,this.delayRam[r]=this.acc,this.acc*=n,this.acc=this.saturate(this.acc)}opWRAP(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask;this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`W`,this.traceDelayValue=this.acc,this.delayRam[r]=this.acc,this.acc=this.acc*n+this.lr,this.acc=this.saturate(this.acc)}opRDAX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=this.registers[t];this.acc+=r*n,this.acc=this.saturate(this.acc)}opWRAX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc*=n,this.acc=this.saturate(this.acc)}opSOF(e){let t=this.decodeS_10(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535);this.acc=this.acc*n+t,this.acc=this.saturate(this.acc)}opRMPA(e){let t=this.decodeS1_9(e>>>21&2047),n=Math.floor(this.registers[24]*this.delaySize),r=this.delayPointer+n&this.delayMask,i=this.delayRam[r];this.traceDelayAddr=r,this.traceDelayOffset=n,this.traceDelayOp=`R`,this.traceDelayValue=i,this.currentReadOffsets.add(n),this.lr=i,this.acc+=i*t,this.acc=this.saturate(this.acc)}opMULX(e){let t=e>>>5&63;this.acc*=this.registers[t],this.acc=this.saturate(this.acc)}opLOG(e){let t=this.decodeS4_6(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535),r=Math.abs(this.acc),i;i=r>152587890625e-16?Math.log2(r):-16,this.acc=(i*n+t)/16,this.acc=this.saturate(this.acc)}opEXP(e){let t=this.decodeS_10(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535),r=this.acc*16;this.acc=2**r*n+t,this.acc=this.saturate(this.acc)}opRDFX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=this.registers[t];this.acc=(this.acc-r)*n+r,this.acc=this.saturate(this.acc)}opMAXX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=Math.abs(this.acc),i=Math.abs(this.registers[t]*n);this.acc=Math.max(r,i),this.acc=this.saturate(this.acc)}opSKP(e){let t=e>>>21&63,n=e&4160749568,r=!1;return n&134217728&&this.acc<0&&(r=!0),n&268435456&&this.acc>=0&&(r=!0),n&536870912&&this.acc===0&&(r=!0),n&1073741824&&this.acc*this.pacc<0&&(r=!0),n&2147483648&&!this.firstRun&&(r=!0),r?t:0}opWRLX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc=(this.pacc-this.acc)*n+this.pacc,this.acc=this.saturate(this.acc)}opWRHX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc=this.pacc+this.acc*n,this.acc=this.saturate(this.acc)}opAND(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n&=t,this.acc=n/8388608}opOR(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n|=t,this.acc=n/8388608}opXOR(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n^=t,this.acc=n/8388608}opJAM(e){let t=e>>>6&3;t===0?this.rmp0=0:t===1&&(this.rmp1=0)}opWLDS(e){let t=e>>>29&1,n=e>>>20&511,r=e>>>5&32767,i=n/512,a=r/32768;t===0?(this.sin0_rate=i,this.sin0_range=a,this.registers[0]=i,this.registers[1]=a,this.cos0=-1,this.sin0=0):(this.sin1_rate=i,this.sin1_range=a,this.registers[2]=i,this.registers[3]=a,this.cos1=-1,this.sin1=0)}opWLDR(e){let t=e>>>29&1,n=e>>>13&65535;n&32768&&(n-=65536);let r=4096>>(e>>>5&3),i=n/16384,a=r/8192;t===0?(this.rmp0_rate=i,this.rmp0_range=a,this.registers[4]=i,this.registers[5]=a,this.rmp0=0):(this.rmp1_rate=i,this.rmp1_range=a,this.registers[6]=i,this.registers[7]=a,this.rmp1=0)}getLfoVal(e,t){return t===0?e&1?this.cos0:this.sin0:t===1?e&1?this.cos1:this.sin1:t===2?this.rmp0:this.rmp1}getLfoRange(e){return e===0?this.sin0_range:e===1?this.sin1_range:e===2?this.rmp0_range:this.rmp1_range}opCHO(e){let t=e>>>30&3;t===0?this.opCHO_RDA(e):t===2?this.opCHO_SOF(e):t===3&&this.opCHO_RDAL(e)}opCHO_RDA(e){let t=e>>>24&63,n=e>>>21&3,r=e>>>5&32767,i=this.getLfoVal(t,n),a=this.getLfoRange(n);a*=8192,t&2&&(this.lfo=i);let o=this.lfo;t&16&&(o+=.5,o>=1&&--o),t&8&&(o=-o);let s,c;if(t&32)s=r,c=Math.min(o,1-o),c=Math.max(0,Math.min(1,4*c-.5));else{let e=o*a+r;s=Math.floor(e),c=e-s}let l=this.delayPointer+s&this.delayMask;this.lr=this.delayRam[l],this.traceDelayAddr=l,this.traceDelayOffset=s,this.traceDelayOp=`R`,this.traceDelayValue=this.lr,this.currentReadOffsets.add(s),t&4&&(c=1-c),this.acc+=this.lr*c,this.acc=this.saturate(this.acc)}opCHO_SOF(e){let t=e>>>24&63,n=e>>>21&3,r=e>>>5&65535,i=this.decodeS_15(r),a=this.getLfoVal(t,n),o=this.getLfoRange(n);t&2&&(this.lfo=a);let s=this.lfo;t&32?(s=Math.min(s,1-s),s=Math.max(0,Math.min(1,4*s-.5))):s*=o,t&4&&(s=1-s),this.acc=s*this.acc+i,this.acc=this.saturate(this.acc)}opCHO_RDAL(e){let t=e>>>24&63,n=e>>>21&3,r=this.getLfoVal(t,n);this.acc=r,this.acc=this.saturate(this.acc)}getPC(){return this.pc}getProgSize(){return this.progSize}setPC(e){this.pc=Math.max(0,Math.min(this.progSize-1,e))}setAcc(e){this.acc=this.saturate(e)}setPacc(e){this.pacc=this.saturate(e)}setRegister(e,t){e<0||e>=32+this.regCount||(t=e>=16&&e<=18?Math.floor(Math.max(0,Math.min(.9999999,t))*1024)/1024:this.saturate(t),this.registers[e]=t)}evaluateExpression(e){let t=e.trim().toUpperCase(),n=``;t.endsWith(`^`)?(n=`^`,t=t.slice(0,-1)):t.endsWith(`#`)&&(n=`#`,t=t.slice(0,-1));let r=this.getState();if(n===``&&r.registers[t]!==void 0)return{label:t,value:r.registers[t]};if(n===``&&t===`ACC`)return{label:`ACC`,value:this.acc};if(n===``&&t===`PACC`)return{label:`PACC`,value:this.pacc};let i=this.symbols.find(e=>e.name.toUpperCase()===t);if(i&&n===``){let e=parseInt(i.value);if(!isNaN(e)&&e>=0&&e<=63)return{label:`REG[${e}] (${i.name})`,value:this.registers[e]}}let a=this.memories.find(e=>e.name.toUpperCase()===t);if(a&&a.start!==void 0){let e=a.start,t=``;if(n===`^`?(e=o.getMiddleAddr(a.start,a.size),t=` (Middle)`):n===`#`&&(e=o.getEndAddr(a.start,a.size,this.fv1AsmMemBug),t=` (End)`),e>=0&&e<this.delaySize)return{label:`MEM[${e}] (${a.name}${t})`,value:this.delayRam[e]}}if(n===``){let e=t.match(/^DELAY\[(\d+)\]$/);if(e){let t=parseInt(e[1]);if(t>=0&&t<this.delaySize)return{label:`DELAY[${t}]`,value:this.delayRam[t]}}}return null}getState(){return{pc:this.pc,acc:this.acc,pacc:this.pacc,lr:this.lr,lfo:this.lfo,registers:Object.fromEntries(Array.from({length:32+this.regCount},(e,t)=>{let n=`[${t}]`;return t===0?n=`SIN0_RATE`:t===1?n=`SIN0_RANGE`:t===2?n=`SIN1_RATE`:t===3?n=`SIN1_RANGE`:t===4?n=`RMP0_RATE`:t===5?n=`RMP0_RANGE`:t===6?n=`RMP1_RATE`:t===7?n=`RMP1_RANGE`:t===8?n=`SIN0`:t===9?n=`COS0`:t===10?n=`SIN1`:t===11?n=`COS1`:t===12?n=`RMP0`:t===13?n=`RMP1`:t===16?n=`POT0`:t===17?n=`POT1`:t===18?n=`POT2`:t===20?n=`ADCL`:t===21?n=`ADCR`:t===22?n=`DACL`:t===23?n=`DACR`:t===24?n=`ADDR_PTR`:t>=32&&t<=63&&(n=`REG${t-32}`),[n,this.registers[t]]})),flags:{RUN:this.firstRun,ZRC:this.acc*this.pacc<0,ZRO:this.acc===0,GEZ:this.acc>=0,NEG:this.acc<0},lfoState:{sin0:this.sin0,cos0:this.cos0,sin1:this.sin1,cos1:this.cos1,rmp0:this.rmp0,rmp1:this.rmp1}}}getCycleCount(){return this.cycleCount}getReadOffsets(){return Array.from(this.currentReadOffsets)}getRegisters(){return this.registers}updateLFOs(){for(this.sin0_rate=this.registers[0],this.sin0_range=this.registers[1],this.sin1_rate=this.registers[2],this.sin1_range=this.registers[3],this.rmp0_rate=this.registers[4],this.rmp0_range=this.registers[5],this.rmp1_rate=this.registers[6],this.rmp1_range=this.registers[7],this.rmp0-=this.rmp0_rate*(1/4096);this.rmp0>=1;)--this.rmp0;for(;this.rmp0<0;)this.rmp0+=1;for(this.rmp1-=this.rmp1_rate*(1/4096);this.rmp1>=1;)--this.rmp1;for(;this.rmp1<0;)this.rmp1+=1;let t=this.sin0_rate*(1/256);this.cos0+=t*this.sin0,this.sin0-=t*this.cos0,this.sin0=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.sin0)),this.cos0=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.cos0));let n=this.sin1_rate*(1/256);this.cos1+=n*this.sin1,this.sin1-=n*this.cos1,this.sin1=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.sin1)),this.cos1=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.cos1))}updateStateRegisters(){this.registers[8]=this.sin0,this.registers[9]=this.cos0,this.registers[10]=this.sin1,this.registers[11]=this.cos1,this.registers[12]=this.rmp0,this.registers[13]=this.rmp1}getDelayRam(){return this.delayRam}decodeS1_14(e){return e&32768?(e-65536)/16384:e/16384}decodeS1_9(e){return e&1024?(e-2048)/512:e/512}decodeS_10(e){return e&1024?(e-2048)/1024:e/1024}decodeS4_6(e){return e&1024?(e-2048)/64:e/64}decodeS_15(e){return e&32768?(e-65536)/32768:e/32768}saturate(t){return t>e.MAX_ACC?e.MAX_ACC:t<e.MIN_ACC?e.MIN_ACC:t}enableTrace(e,t=0,n){this.traceEnabled=!0,this.traceWriter=e,this.traceMaxCycles=t,this.traceCycle=0,this.traceRowCount=0,this.traceOnComplete=n||null,e(`cycle,pc,opcode,delay_op,delay_offset,delay_addr,delay_ptr`),console.log(`[FV1 Trace] Logging enabled (maxCycles=${t||`unlimited`})`)}disableTrace(){this.traceEnabled=!1,this.traceWriter=null,console.log(`[FV1 Trace] Logging disabled. ${this.traceRowCount} rows written.`)}isTraceEnabled(){return this.traceEnabled}getTraceRowCount(){return this.traceRowCount}advanceTraceCycle(){if(this.traceEnabled&&(this.traceCycle++,this.traceMaxCycles>0&&this.traceCycle>=this.traceMaxCycles)){let e=this.traceOnComplete;this.disableTrace(),e&&e()}}logTrace(t,n,r,i){if(!this.traceWriter||this.traceDelayOp===``)return;let a=e.OPCODE_NAMES[n]||`?${n.toString(16)}`;if(n===20){let e=r>>>30&3;if(e===0)a=`CHO_RDA`;else if(e===2)return;else e===3&&(a=`CHO_RDAL`)}else if(n===18)return;let o=`${this.traceCycle},${t},${a},${this.traceDelayOp},${this.traceDelayOp===``?``:this.traceDelayOffset},${this.traceDelayAddr>=0?this.traceDelayAddr:``},${this.delayPointer}`;this.traceWriter(o),this.traceRowCount++}};s.MAX_ACC=1-1/8388608,s.MIN_ACC=-s.MAX_ACC,s.OPCODE_NAMES={0:`RDA`,1:`RMPA`,2:`WRA`,3:`WRAP`,4:`RDAX`,5:`RDFX`,6:`WRAX`,7:`WRHX`,8:`WRLX`,9:`MAXX`,10:`MULX`,11:`LOG`,12:`EXP`,13:`SOF`,14:`AND`,15:`OR`,16:`XOR`,17:`SKP`,18:`WLDx`,19:`JAM`,20:`CHO`};var c=class extends AudioWorkletProcessor{simulator=new s;pot=[.5,.5,.5];bypassed=!1;channelMode=`mono`;constructor(){super(),this.simulator.setPotSmoothing(.03,sampleRate),this.port.onmessage=({data:e})=>{switch(e.type){case`loadProgram`:this.simulator.loadProgram(new Uint32Array(e.machineCode));break;case`setPot`:this.pot[e.index]=e.value;break;case`bypass`:this.bypassed=e.active;break;case`setChannelMode`:this.channelMode=e.mode===`stereo`?`stereo`:`mono`;break}}}process(e,t){let n=e[0],r=t[0];if(!n?.length||!r?.length)return!0;let i=n[0],a=n[1]??i,o=r[0],s=r[1]??o;return this.bypassed?(o.set(i),r[1]&&s.set(a),!0):(this.simulator.processBlock(i,a,o,s,this.pot[0],this.pot[1],this.pot[2]),this.channelMode===`mono`&&r[1]&&s.set(o),!0)}};registerProcessor(`fv1-processor`,c)})();
|
|
7
|
+
`)}static toUint8Array(e){let t=new ArrayBuffer(e.length*4),n=new DataView(t);return e.forEach((e,t)=>n.setUint32(t*4,e,!1)),new Uint8Array(t)}static getMiddleAddr(e,t){return e+(t%2?(t-1)/2-1:t/2)}static getEndAddr(e,t,n){return e+t-1+ +!!n}},s=class e{constructor(){this.delaySize=32768,this.delayMask=32767,this.regCount=32,this.progSize=128,this.sin0=0,this.cos0=0,this.sin1=0,this.cos1=0,this.rmp0=0,this.rmp1=0,this.sin0_rate=0,this.sin0_range=0,this.sin1_rate=0,this.sin1_range=0,this.rmp0_rate=0,this.rmp0_range=0,this.rmp1_rate=0,this.rmp1_range=0,this.acc=0,this.pacc=0,this.lr=0,this.lfo=0,this.delayPointer=0,this.firstRun=!0,this.pc=0,this.breakpoints=new Set,this.symbols=[],this.memories=[],this.fv1AsmMemBug=!1,this.traceEnabled=!1,this.traceWriter=null,this.cycleCount=0,this.traceCycle=0,this.traceMaxCycles=0,this.traceRowCount=0,this.traceDelayAddr=-1,this.traceDelayOffset=-1,this.traceDelayOp=``,this.traceDelayValue=0,this.traceInstructionPC=-1,this.currentReadOffsets=new Set,this.traceOnComplete=null,this.delayRam=new Float32Array(this.delaySize),this.registers=new Float32Array(32+this.regCount),this.program=new Uint32Array(this.progSize)}setCapabilities(e,t,n){this.delaySize=e,this.delayMask=e-1,this.regCount=t,this.progSize=n,this.delayRam=new Float32Array(this.delaySize),this.registers=new Float32Array(32+this.regCount),this.program=new Uint32Array(this.progSize),this.reset()}getDelayPointer(){return this.delayPointer}getDelaySize(){return this.delaySize}loadProgram(e){e.length>this.progSize&&console.warn(`Program size (${e.length}) exceeds max size (${this.progSize}). Truncating.`),this.program.fill(0),this.program.set(e.slice(0,this.progSize)),this.reset()}reset(){this.delayRam.fill(0),this.registers.fill(0),this.acc=0,this.pacc=0,this.lr=0,this.lfo=0,this.pc=0,this.delayPointer=0,this.firstRun=!0,this.sin0=0,this.sin1=0,this.cos0=-1,this.cos1=-1,this.rmp0=0,this.rmp1=0,this.sin0_rate=0,this.sin0_range=0,this.sin1_rate=0,this.sin1_range=0,this.rmp0_rate=0,this.rmp0_range=0,this.rmp1_rate=0,this.rmp1_range=0,this.registers[16]=.5,this.registers[17]=.5,this.registers[18]=.5}setBreakpoints(e){this.breakpoints=e}setSymbols(e,t,n=!1){this.symbols=e,this.memories=t,this.fv1AsmMemBug=n}processBlock(e,t,n,r,i,a,o){let s=e.length;for(let c=0;c<s;c++){let[s,l]=this.step(e[c],t[c],i,a,o);n[c]=s,r[c]=l}}step(e,t,n,r,i,a=!1){this.pc===0&&this.beginFrame(e,t,n,r,i);let o=!0;for(;this.pc<this.progSize;){if(this.breakpoints.has(this.pc)&&(!o||!a))return[...this.getOutputs(),!0];this.stepInstruction(),o=!1}return[...this.endFrame(),!1]}getOutputs(){return[this.registers[22],this.registers[23]]}beginFrame(t=0,n=0,r=0,i=0,a=0){this.cycleCount++,this.currentReadOffsets.clear();let o=t=>Math.max(-1,Math.min(e.MAX_ACC,t)),s=e=>Math.floor(Math.max(0,Math.min(.9999999,e))*1024)/1024;this.acc=0,this.lr=0,this.pacc=0,this.pc=0,this.registers[20]=o(t),this.registers[21]=o(n),this.registers[16]=s(r),this.registers[17]=s(i),this.registers[18]=s(a),this.updateStateRegisters()}endFrame(){return this.pc=0,this.firstRun=!1,this.updateLFOs(),this.updateStateRegisters(),this.advanceTraceCycle(),this.delayPointer=(this.delayPointer-1+this.delaySize)%this.delaySize,[this.registers[22],this.registers[23]]}stepInstruction(){if(this.pc>=this.progSize)return this.pc;let e=this.program[this.pc],t=e&31,n=this.acc;this.traceDelayAddr=-1,this.traceDelayOffset=-1,this.traceDelayOp=``,this.traceDelayValue=0,this.traceInstructionPC=this.pc;let r=this.executeInstruction(e);return this.traceEnabled&&this.logTrace(this.traceInstructionPC,t,e,n),t!==17&&(this.pacc=n),this.pc+=1+r,this.pc}executeInstruction(e){let t=e&31,n=0;switch(t){case 0:this.opRDA(e);break;case 1:this.opRMPA(e);break;case 2:this.opWRA(e);break;case 3:this.opWRAP(e);break;case 4:this.opRDAX(e);break;case 5:this.opRDFX(e);break;case 6:this.opWRAX(e);break;case 7:this.opWRHX(e);break;case 8:this.opWRLX(e);break;case 9:this.opMAXX(e);break;case 10:this.opMULX(e);break;case 11:this.opLOG(e);break;case 12:this.opEXP(e);break;case 13:this.opSOF(e);break;case 14:this.opAND(e);break;case 15:this.opOR(e);break;case 16:this.opXOR(e);break;case 17:n=this.opSKP(e);break;case 18:e>>>30&1?this.opWLDR(e):this.opWLDS(e);break;case 19:this.opJAM(e);break;case 20:this.opCHO(e);break;default:break}return n}opRDA(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask,i=this.delayRam[r];this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`R`,this.traceDelayValue=i,this.currentReadOffsets.add(t),this.lr=i,this.acc+=i*n,this.acc=this.saturate(this.acc)}opWRA(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask;this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`W`,this.traceDelayValue=this.acc,this.delayRam[r]=this.acc,this.acc*=n,this.acc=this.saturate(this.acc)}opWRAP(e){let t=e>>>5&32767,n=this.decodeS1_9(e>>>21&2047),r=this.delayPointer+t&this.delayMask;this.traceDelayAddr=r,this.traceDelayOffset=t,this.traceDelayOp=`W`,this.traceDelayValue=this.acc,this.delayRam[r]=this.acc,this.acc=this.acc*n+this.lr,this.acc=this.saturate(this.acc)}opRDAX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=this.registers[t];this.acc+=r*n,this.acc=this.saturate(this.acc)}opWRAX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc*=n,this.acc=this.saturate(this.acc)}opSOF(e){let t=this.decodeS_10(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535);this.acc=this.acc*n+t,this.acc=this.saturate(this.acc)}opRMPA(e){let t=this.decodeS1_9(e>>>21&2047),n=Math.trunc(this.registers[24]*this.delaySize),r=this.delayPointer+n&this.delayMask,i=this.delayRam[r];this.traceDelayAddr=r,this.traceDelayOffset=n,this.traceDelayOp=`R`,this.traceDelayValue=i,this.currentReadOffsets.add(n),this.lr=i,this.acc+=i*t,this.acc=this.saturate(this.acc)}opMULX(e){let t=e>>>5&63;this.acc*=this.registers[t],this.acc=this.saturate(this.acc)}opLOG(e){let t=this.decodeS4_6(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535),r=Math.abs(this.acc),i;i=r>152587890625e-16?Math.log2(r):-16,this.acc=(i*n+t)/16,this.acc=this.saturate(this.acc)}opEXP(e){let t=this.decodeS_10(e>>>5&2047),n=this.decodeS1_14(e>>>16&65535),r=this.acc*16;this.acc=2**r*n+t,this.acc=this.saturate(this.acc)}opRDFX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=this.registers[t];this.acc=(this.acc-r)*n+r,this.acc=this.saturate(this.acc)}opMAXX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535),r=Math.abs(this.acc),i=Math.abs(this.registers[t]*n);this.acc=Math.max(r,i),this.acc=this.saturate(this.acc)}opSKP(e){let t=e>>>21&63,n=e&4160749568,r=!1;return n&134217728&&this.acc<0&&(r=!0),n&268435456&&this.acc>=0&&(r=!0),n&536870912&&this.acc===0&&(r=!0),n&1073741824&&this.acc*this.pacc<0&&(r=!0),n&2147483648&&!this.firstRun&&(r=!0),r?t:0}opWRLX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc=(this.pacc-this.acc)*n+this.pacc,this.acc=this.saturate(this.acc)}opWRHX(e){let t=e>>>5&63,n=this.decodeS1_14(e>>>16&65535);this.registers[t]=this.acc,this.acc=this.pacc+this.acc*n,this.acc=this.saturate(this.acc)}opAND(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n&=t,this.acc=n/8388608}opOR(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n|=t,this.acc=n/8388608}opXOR(e){let t=e>>>8&16777215,n=Math.floor(this.acc*8388608);n^=t,this.acc=n/8388608}opJAM(e){let t=e>>>6&3;t===0?this.rmp0=0:t===1&&(this.rmp1=0)}opWLDS(e){let t=e>>>29&1,n=e>>>20&511,r=e>>>5&32767,i=n/512,a=r/32768;t===0?(this.sin0_rate=i,this.sin0_range=a,this.registers[0]=i,this.registers[1]=a,this.cos0=-1,this.sin0=0):(this.sin1_rate=i,this.sin1_range=a,this.registers[2]=i,this.registers[3]=a,this.cos1=-1,this.sin1=0)}opWLDR(e){let t=e>>>29&1,n=e>>>13&65535;n&32768&&(n-=65536);let r=4096>>(e>>>5&3),i=n/16384,a=r/8192;t===0?(this.rmp0_rate=i,this.rmp0_range=a,this.registers[4]=i,this.registers[5]=a,this.rmp0=0):(this.rmp1_rate=i,this.rmp1_range=a,this.registers[6]=i,this.registers[7]=a,this.rmp1=0)}getLfoVal(e,t){return t===0?e&1?this.cos0:this.sin0:t===1?e&1?this.cos1:this.sin1:t===2?this.rmp0:this.rmp1}getLfoRange(e){return e===0?this.sin0_range:e===1?this.sin1_range:e===2?this.rmp0_range:this.rmp1_range}opCHO(e){let t=e>>>30&3;t===0?this.opCHO_RDA(e):t===2?this.opCHO_SOF(e):t===3&&this.opCHO_RDAL(e)}opCHO_RDA(e){let t=e>>>24&63,n=e>>>21&3,r=e>>>5&32767,i=this.getLfoVal(t,n),a=this.getLfoRange(n);a*=8192,t&2&&(this.lfo=i);let o=this.lfo;t&16&&(o+=.5,o>=1&&--o),t&8&&(o=-o);let s,c;if(t&32)s=r,c=Math.min(o,1-o),c=Math.max(0,Math.min(1,4*c-.5));else{let e=o*a+r;s=Math.floor(e),c=e-s}let l=this.delayPointer+s&this.delayMask;this.lr=this.delayRam[l],this.traceDelayAddr=l,this.traceDelayOffset=s,this.traceDelayOp=`R`,this.traceDelayValue=this.lr,this.currentReadOffsets.add(s),t&4&&(c=1-c),this.acc+=this.lr*c,this.acc=this.saturate(this.acc)}opCHO_SOF(e){let t=e>>>24&63,n=e>>>21&3,r=e>>>5&65535,i=this.decodeS_15(r),a=this.getLfoVal(t,n),o=this.getLfoRange(n);t&2&&(this.lfo=a);let s=this.lfo;t&32?(s=Math.min(s,1-s),s=Math.max(0,Math.min(1,4*s-.5))):s*=o,t&4&&(s=1-s),this.acc=s*this.acc+i,this.acc=this.saturate(this.acc)}opCHO_RDAL(e){let t=e>>>24&63,n=e>>>21&3,r=this.getLfoVal(t,n);this.acc=r,this.acc=this.saturate(this.acc)}getPC(){return this.pc}getProgSize(){return this.progSize}setPC(e){this.pc=Math.max(0,Math.min(this.progSize-1,e))}setAcc(e){this.acc=this.saturate(e)}setPacc(e){this.pacc=this.saturate(e)}setRegister(e,t){e<0||e>=32+this.regCount||(t=e>=16&&e<=18?Math.floor(Math.max(0,Math.min(.9999999,t))*1024)/1024:this.saturate(t),this.registers[e]=t)}evaluateExpression(e){let t=e.trim().toUpperCase(),n=``;t.endsWith(`^`)?(n=`^`,t=t.slice(0,-1)):t.endsWith(`#`)&&(n=`#`,t=t.slice(0,-1));let r=this.getState();if(n===``&&r.registers[t]!==void 0)return{label:t,value:r.registers[t]};if(n===``&&t===`ACC`)return{label:`ACC`,value:this.acc};if(n===``&&t===`PACC`)return{label:`PACC`,value:this.pacc};let i=this.symbols.find(e=>e.name.toUpperCase()===t);if(i&&n===``){let e=parseInt(i.value);if(!isNaN(e)&&e>=0&&e<=63)return{label:`REG[${e}] (${i.name})`,value:this.registers[e]}}let a=this.memories.find(e=>e.name.toUpperCase()===t);if(a&&a.start!==void 0){let e=a.start,t=``;if(n===`^`?(e=o.getMiddleAddr(a.start,a.size),t=` (Middle)`):n===`#`&&(e=o.getEndAddr(a.start,a.size,this.fv1AsmMemBug),t=` (End)`),e>=0&&e<this.delaySize)return{label:`MEM[${e}] (${a.name}${t})`,value:this.delayRam[e]}}if(n===``){let e=t.match(/^DELAY\[(\d+)\]$/);if(e){let t=parseInt(e[1]);if(t>=0&&t<this.delaySize)return{label:`DELAY[${t}]`,value:this.delayRam[t]}}}return null}getState(){return{pc:this.pc,acc:this.acc,pacc:this.pacc,lr:this.lr,lfo:this.lfo,registers:Object.fromEntries(Array.from({length:32+this.regCount},(e,t)=>{let n=`[${t}]`;return t===0?n=`SIN0_RATE`:t===1?n=`SIN0_RANGE`:t===2?n=`SIN1_RATE`:t===3?n=`SIN1_RANGE`:t===4?n=`RMP0_RATE`:t===5?n=`RMP0_RANGE`:t===6?n=`RMP1_RATE`:t===7?n=`RMP1_RANGE`:t===8?n=`SIN0`:t===9?n=`COS0`:t===10?n=`SIN1`:t===11?n=`COS1`:t===12?n=`RMP0`:t===13?n=`RMP1`:t===16?n=`POT0`:t===17?n=`POT1`:t===18?n=`POT2`:t===20?n=`ADCL`:t===21?n=`ADCR`:t===22?n=`DACL`:t===23?n=`DACR`:t===24?n=`ADDR_PTR`:t>=32&&t<=63&&(n=`REG${t-32}`),[n,this.registers[t]]})),flags:{RUN:this.firstRun,ZRC:this.acc*this.pacc<0,ZRO:this.acc===0,GEZ:this.acc>=0,NEG:this.acc<0},lfoState:{sin0:this.sin0,cos0:this.cos0,sin1:this.sin1,cos1:this.cos1,rmp0:this.rmp0,rmp1:this.rmp1}}}getCycleCount(){return this.cycleCount}getReadOffsets(){return Array.from(this.currentReadOffsets)}getRegisters(){return this.registers}updateLFOs(){for(this.sin0_rate=this.registers[0],this.sin0_range=this.registers[1],this.sin1_rate=this.registers[2],this.sin1_range=this.registers[3],this.rmp0_rate=this.registers[4],this.rmp0_range=this.registers[5],this.rmp1_rate=this.registers[6],this.rmp1_range=this.registers[7],this.rmp0-=this.rmp0_rate*(1/4096);this.rmp0>=1;)--this.rmp0;for(;this.rmp0<0;)this.rmp0+=1;for(this.rmp1-=this.rmp1_rate*(1/4096);this.rmp1>=1;)--this.rmp1;for(;this.rmp1<0;)this.rmp1+=1;let t=this.sin0_rate*(1/256);this.cos0+=t*this.sin0,this.sin0-=t*this.cos0,this.sin0=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.sin0)),this.cos0=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.cos0));let n=this.sin1_rate*(1/256);this.cos1+=n*this.sin1,this.sin1-=n*this.cos1,this.sin1=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.sin1)),this.cos1=Math.max(e.MIN_ACC,Math.min(e.MAX_ACC,this.cos1))}updateStateRegisters(){this.registers[8]=this.sin0,this.registers[9]=this.cos0,this.registers[10]=this.sin1,this.registers[11]=this.cos1,this.registers[12]=this.rmp0,this.registers[13]=this.rmp1}getDelayRam(){return this.delayRam}decodeS1_14(e){return e&32768?(e-65536)/16384:e/16384}decodeS1_9(e){return e&1024?(e-2048)/512:e/512}decodeS_10(e){return e&1024?(e-2048)/1024:e/1024}decodeS4_6(e){return e&1024?(e-2048)/64:e/64}decodeS_15(e){return e&32768?(e-65536)/32768:e/32768}saturate(t){return t>e.MAX_ACC?e.MAX_ACC:t<e.MIN_ACC?e.MIN_ACC:t}enableTrace(e,t=0,n){this.traceEnabled=!0,this.traceWriter=e,this.traceMaxCycles=t,this.traceCycle=0,this.traceRowCount=0,this.traceOnComplete=n||null,e(`cycle,pc,opcode,delay_op,delay_offset,delay_addr,delay_ptr`),console.log(`[FV1 Trace] Logging enabled (maxCycles=${t||`unlimited`})`)}disableTrace(){this.traceEnabled=!1,this.traceWriter=null,console.log(`[FV1 Trace] Logging disabled. ${this.traceRowCount} rows written.`)}isTraceEnabled(){return this.traceEnabled}getTraceRowCount(){return this.traceRowCount}advanceTraceCycle(){if(this.traceEnabled&&(this.traceCycle++,this.traceMaxCycles>0&&this.traceCycle>=this.traceMaxCycles)){let e=this.traceOnComplete;this.disableTrace(),e&&e()}}logTrace(t,n,r,i){if(!this.traceWriter||this.traceDelayOp===``)return;let a=e.OPCODE_NAMES[n]||`?${n.toString(16)}`;if(n===20){let e=r>>>30&3;if(e===0)a=`CHO_RDA`;else if(e===2)return;else e===3&&(a=`CHO_RDAL`)}else if(n===18)return;let o=`${this.traceCycle},${t},${a},${this.traceDelayOp},${this.traceDelayOp===``?``:this.traceDelayOffset},${this.traceDelayAddr>=0?this.traceDelayAddr:``},${this.delayPointer}`;this.traceWriter(o),this.traceRowCount++}};s.MAX_ACC=1-1/8388608,s.MIN_ACC=-s.MAX_ACC,s.OPCODE_NAMES={0:`RDA`,1:`RMPA`,2:`WRA`,3:`WRAP`,4:`RDAX`,5:`RDFX`,6:`WRAX`,7:`WRHX`,8:`WRLX`,9:`MAXX`,10:`MULX`,11:`LOG`,12:`EXP`,13:`SOF`,14:`AND`,15:`OR`,16:`XOR`,17:`SKP`,18:`WLDx`,19:`JAM`,20:`CHO`};var c=class extends AudioWorkletProcessor{simulator=new s;pot=[.5,.5,.5];bypassed=!1;channelMode=`mono`;constructor(){super(),this.port.onmessage=({data:e})=>{switch(e.type){case`loadProgram`:this.simulator.loadProgram(new Uint32Array(e.machineCode));break;case`setPot`:this.pot[e.index]=e.value;break;case`bypass`:this.bypassed=e.active;break;case`setChannelMode`:this.channelMode=e.mode===`stereo`?`stereo`:`mono`;break}}}process(e,t){let n=e[0],r=t[0];if(!n?.length||!r?.length)return!0;let i=n[0],a=n[1]??i,o=r[0],s=r[1]??o;return this.bypassed?(o.set(i),r[1]&&s.set(a),!0):(this.simulator.processBlock(i,a,o,s,this.pot[0],this.pot[1],this.pot[2]),this.channelMode===`mono`&&r[1]&&s.set(o),!0)}};registerProcessor(`fv1-processor`,c)})();
|
|
8
8
|
//# sourceMappingURL=fv1-processor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fv1-processor.js","names":[],"sources":["../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Parser.js","../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Encoder.js","../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Assembler.js","../../node_modules/@audiofab-io/fv1-core/dist/simulator/FV1Simulator.js","../../src/worklet/fv1-processor.ts"],"sourcesContent":["export class ParserError extends Error {\n constructor(message, line, column) {\n super(message);\n this.line = line;\n this.column = column;\n this.name = 'ParserError';\n }\n}\nexport var TokenType;\n(function (TokenType) {\n TokenType[TokenType[\"IDENTIFIER\"] = 0] = \"IDENTIFIER\";\n TokenType[TokenType[\"NUMBER\"] = 1] = \"NUMBER\";\n TokenType[TokenType[\"MNEMONIC\"] = 2] = \"MNEMONIC\";\n TokenType[TokenType[\"DIRECTIVE\"] = 3] = \"DIRECTIVE\";\n TokenType[TokenType[\"OPERATOR\"] = 4] = \"OPERATOR\";\n TokenType[TokenType[\"COMMA\"] = 5] = \"COMMA\";\n TokenType[TokenType[\"COLON\"] = 6] = \"COLON\";\n TokenType[TokenType[\"NEWLINE\"] = 7] = \"NEWLINE\";\n TokenType[TokenType[\"EOF\"] = 8] = \"EOF\";\n TokenType[TokenType[\"LPAREN\"] = 9] = \"LPAREN\";\n TokenType[TokenType[\"RPAREN\"] = 10] = \"RPAREN\";\n})(TokenType || (TokenType = {}));\nexport class Lexer {\n constructor(source) {\n this.source = source;\n this.pos = 0;\n this.line = 1;\n this.column = 1;\n }\n peek() {\n return this.source[this.pos] || '';\n }\n advance() {\n const char = this.peek();\n this.pos++;\n if (char === '\\n') {\n this.line++;\n this.column = 1;\n }\n else {\n this.column++;\n }\n return char;\n }\n tokenize() {\n const tokens = [];\n while (this.pos < this.source.length) {\n const char = this.peek();\n if (/\\s/.test(char) && char !== '\\n') {\n this.advance();\n }\n else if (char === ';') {\n // Skip comments\n while (this.peek() !== '\\n' && this.pos < this.source.length) {\n this.advance();\n }\n }\n else if (char === '\\n') {\n tokens.push({ type: TokenType.NEWLINE, value: '\\n', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ',') {\n tokens.push({ type: TokenType.COMMA, value: ',', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ':') {\n tokens.push({ type: TokenType.COLON, value: ':', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === '(') {\n tokens.push({ type: TokenType.LPAREN, value: '(', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ')') {\n tokens.push({ type: TokenType.RPAREN, value: ')', line: this.line, column: this.column });\n this.advance();\n }\n else if (/[a-zA-Z_]/.test(char)) {\n tokens.push(this.readIdentifier());\n }\n else if (/[0-9.]/.test(char) || char === '$' || char === '%') {\n tokens.push(this.readNumber());\n }\n else if (/[-+*/|&<>^!]/.test(char)) {\n tokens.push({ type: TokenType.OPERATOR, value: this.advance(), line: this.line, column: this.column });\n }\n else {\n // Unknown character\n this.advance();\n }\n }\n tokens.push({ type: TokenType.EOF, value: '', line: this.line, column: this.column });\n return tokens;\n }\n readIdentifier() {\n let value = '';\n const startLine = this.line;\n const startCol = this.column;\n while (/[a-zA-Z0-9_#^.]/.test(this.peek())) {\n value += this.advance();\n }\n const upper = value.toUpperCase();\n if (['EQU', 'MEM'].includes(upper)) {\n return { type: TokenType.DIRECTIVE, value: upper, line: startLine, column: startCol };\n }\n // Mnemonics are checked during parsing or here. Let's keep them as identifiers for now \n // and resolve them in the parser.\n return { type: TokenType.IDENTIFIER, value: upper, line: startLine, column: startCol };\n }\n readNumber() {\n let value = '';\n const startLine = this.line;\n const startCol = this.column;\n if (this.peek() === '$') {\n value += this.advance();\n while (/[0-9a-fA-F]/.test(this.peek()))\n value += this.advance();\n }\n else if (this.peek() === '%') {\n value += this.advance();\n while (/[01_]/.test(this.peek()))\n value += this.advance();\n }\n else if (this.peek() === '0' && (this.source[this.pos + 1] || '').toLowerCase() === 'x') {\n value += this.advance(); // 0\n value += this.advance(); // x\n while (/[0-9a-fA-F]/.test(this.peek()))\n value += this.advance();\n }\n else {\n while (/[0-9\\.]/.test(this.peek()))\n value += this.advance();\n }\n return { type: TokenType.NUMBER, value, line: startLine, column: startCol };\n }\n}\nexport class Parser {\n constructor(tokens) {\n this.pos = 0;\n this.tokens = tokens.filter((t, i) => t.type !== TokenType.NEWLINE || this.isNextSignificant(tokens, i));\n }\n isNextSignificant(tokens, index) {\n // Only keep newlines if they are followed by something that isn't a newline or EOF\n for (let i = index + 1; i < tokens.length; i++) {\n if (tokens[i].type !== TokenType.NEWLINE) {\n return tokens[i].type !== TokenType.EOF;\n }\n }\n return false;\n }\n peek() {\n return this.tokens[this.pos] || { type: TokenType.EOF, value: '', line: -1, column: -1 };\n }\n advance() {\n return this.tokens[this.pos++];\n }\n match(type) {\n if (this.peek().type === type)\n return this.advance();\n return null;\n }\n parse() {\n const nodes = [];\n while (this.peek().type !== TokenType.EOF) {\n const node = this.parseStatement();\n if (node)\n nodes.push(node);\n // Consume optional newline\n while (this.match(TokenType.NEWLINE))\n ;\n }\n return nodes;\n }\n parseStatement() {\n const token = this.peek();\n if (token.type === TokenType.IDENTIFIER) {\n const next = this.tokens[this.pos + 1];\n // Label: IDENTIFIER:\n if (next && next.type === TokenType.COLON) {\n const label = this.advance();\n this.advance(); // consume :\n return { type: 'Label', name: label.value, line: label.line };\n }\n // Directive: IDENTIFIER EQU EXPR or EQU IDENTIFIER EXPR\n if (next && next.type === TokenType.DIRECTIVE) {\n const id = this.advance();\n const dir = this.advance();\n const expr = this.parseExpression();\n return { type: 'Directive', name: dir.value, identifier: id.value, expression: expr, line: dir.line };\n }\n }\n if (token.type === TokenType.DIRECTIVE) {\n const dir = this.advance();\n const id = this.match(TokenType.IDENTIFIER);\n if (!id)\n throw new ParserError(`Expected identifier after ${dir.value}`, dir.line, dir.column);\n const expr = this.parseExpression();\n return { type: 'Directive', name: dir.value, identifier: id.value, expression: expr, line: dir.line };\n }\n if (token.type === TokenType.IDENTIFIER) {\n const mnemonic = this.advance();\n const operands = [];\n if (this.peek().type !== TokenType.NEWLINE && this.peek().type !== TokenType.EOF) {\n operands.push(this.parseExpression());\n while (this.match(TokenType.COMMA)) {\n operands.push(this.parseExpression());\n }\n }\n return { type: 'Instruction', mnemonic: mnemonic.value, operands, line: mnemonic.line };\n }\n this.advance(); // Skip unknown\n return null;\n }\n parseExpression() {\n return this.parseBitwise();\n }\n parseBitwise() {\n let left = this.parseShift();\n while (this.peek().type === TokenType.OPERATOR && (['|', '&', '^'].includes(this.peek().value))) {\n const operator = this.advance().value;\n const right = this.parseShift();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseShift() {\n let left = this.parseAdditive();\n while (this.peek().type === TokenType.OPERATOR && (['<', '>'].includes(this.peek().value))) {\n const operator = this.advance().value;\n const right = this.parseAdditive();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseAdditive() {\n let left = this.parseMultiplicative();\n while (this.peek().type === TokenType.OPERATOR && (this.peek().value === '+' || this.peek().value === '-')) {\n const operator = this.advance().value;\n const right = this.parseMultiplicative();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseMultiplicative() {\n let left = this.parsePrimary();\n while (this.peek().type === TokenType.OPERATOR && (this.peek().value === '*' || this.peek().value === '/')) {\n const operator = this.advance().value;\n const right = this.parsePrimary();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parsePrimary() {\n const token = this.peek();\n if (token.type === TokenType.NUMBER) {\n return { type: 'Number', value: this.parseNumberValue(this.advance().value) };\n }\n if (token.type === TokenType.IDENTIFIER) {\n return { type: 'Identifier', name: this.advance().value };\n }\n if (token.type === TokenType.LPAREN) {\n this.advance();\n const expr = this.parseExpression();\n if (!this.match(TokenType.RPAREN))\n throw new ParserError(`Expected )`, token.line, token.column);\n return expr;\n }\n if (token.type === TokenType.OPERATOR && (token.value === '-' || token.value === '+' || token.value === '!')) {\n const operator = this.advance().value;\n return { type: 'Unary', operator, expression: this.parsePrimary() };\n }\n throw new ParserError(`Unexpected token ${token.value}`, token.line, token.column);\n }\n parseNumberValue(val) {\n const upper = val.toUpperCase();\n if (upper.startsWith('$'))\n return parseInt(val.slice(1), 16);\n if (upper.startsWith('0X'))\n return parseInt(val, 16);\n if (upper.startsWith('%'))\n return parseInt(val.slice(1).replace(/_/g, ''), 2);\n return parseFloat(val);\n }\n}\n//# sourceMappingURL=FV1Parser.js.map","export const INSTRUCTION_SET = {\n // Accumulator\n 'SOF': {\n opcode: 0b01101, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S_10' },\n { name: 'op', bits: 5, offset: 0, value: 0b01101 }\n ]\n },\n 'AND': {\n opcode: 0b01110, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b01110 }\n ]\n },\n 'OR': {\n opcode: 0b01111, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b01111 }\n ]\n },\n 'XOR': {\n opcode: 0b10000, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b10000 }\n ]\n },\n 'LOG': {\n opcode: 0b01011, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S4_6' },\n { name: 'op', bits: 5, offset: 0, value: 0b01011 }\n ]\n },\n 'EXP': {\n opcode: 0b01100, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S_10' },\n { name: 'op', bits: 5, offset: 0, value: 0b01100 }\n ]\n },\n 'SKP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, type: 'LFO' }, // Special handling for flag bits\n { name: 'n', bits: 6, offset: 21, type: 'S' },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n 'JMP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, value: 0 },\n { name: 'n', bits: 6, offset: 21, type: 'S' },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n 'NOP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, value: 0 },\n { name: 'n', bits: 6, offset: 21, value: 0 },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n // Register\n 'RDAX': {\n opcode: 0b00100, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00100 }\n ]\n },\n 'WRAX': {\n opcode: 0b00110, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00110 }\n ]\n },\n 'MAXX': {\n opcode: 0b01001, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b01001 }\n ]\n },\n 'MULX': {\n opcode: 0b01010, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'op', bits: 5, offset: 0, value: 0b01010 }\n ]\n },\n 'RDFX': {\n opcode: 0b00101, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00101 }\n ]\n },\n 'WRLX': {\n opcode: 0b01000, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b01000 }\n ]\n },\n 'WRHX': {\n opcode: 0b00111, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00111 }\n ]\n },\n 'LDAX': {\n opcode: 0b00101, fields: [\n { name: 'coeff', bits: 16, offset: 16, value: 0 },\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'op', bits: 5, offset: 0, value: 0b00101 }\n ]\n },\n // Delay RAM\n 'RDA': {\n opcode: 0b00000, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00000 }\n ]\n },\n 'RMPA': {\n opcode: 0b00001, fields: [\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00001 }\n ]\n },\n 'WRA': {\n opcode: 0b00010, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00010 }\n ]\n },\n 'WRAP': {\n opcode: 0b00011, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00011 }\n ]\n },\n // LFO/CHO\n 'WLDS': {\n opcode: 0b10010, fields: [\n { name: 'sinLfo', bits: 1, offset: 29, type: 'U' }, // N\n { name: 'freq', bits: 9, offset: 20, type: 'U' }, // F\n { name: 'ampl', bits: 15, offset: 5, type: 'U' }, // A\n { name: 'op', bits: 5, offset: 0, value: 0b10010 }\n ]\n },\n 'WLDR': {\n opcode: 0b10010, fields: [\n { name: 'type', bits: 1, offset: 30, value: 1 }, // Always 1 for WLDR\n { name: 'rmpLfo', bits: 1, offset: 29, type: 'U' }, // N\n { name: 'freq', bits: 16, offset: 13, type: 'U' }, // F (signed 16-bit)\n { name: 'ampl', bits: 2, offset: 5, type: 'U' }, // A (backward encoding handled in assembler)\n { name: 'op', bits: 5, offset: 0, value: 0b10010 }\n ]\n },\n 'JAM': {\n opcode: 0b10011, fields: [\n { name: 'rmpLfo', bits: 1, offset: 6, type: 'U' },\n { name: 'type', bits: 1, offset: 7, value: 1 },\n { name: 'op', bits: 5, offset: 0, value: 0b10011 }\n ]\n },\n 'CHO': {\n opcode: 0b10100, fields: [\n { name: 'mode', bits: 2, offset: 30, type: 'U' },\n { name: 'flags', bits: 6, offset: 24, type: 'U' },\n { name: 'n', bits: 3, offset: 21, type: 'U' },\n { name: 'param', bits: 16, offset: 5, type: 'ADDR' }, // Can be addr or coeff\n { name: 'op', bits: 5, offset: 0, value: 0b10100 }\n ]\n },\n // Pseudo-ops\n 'CLR': { opcode: 0b01110, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b01110 }] },\n 'NOT': { opcode: 0b10000, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b10000 }] },\n 'ABSA': { opcode: 0b01001, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b01001 }] },\n};\nexport class Encoder {\n static encode(format, value) {\n switch (format) {\n case 'S1_14': return this.toFixedPoint(value, 1, 14, 2.0);\n case 'S_15': return this.toFixedPoint(value, 0, 15, 1.0);\n case 'S1_9': return this.toFixedPoint(value, 1, 9, 2.0);\n case 'S_10': return this.toFixedPoint(value, 0, 10, 1.0);\n case 'S4_6': return this.toFixedPoint(value, 4, 6, 16.0);\n }\n return value;\n }\n static toFixedPoint(value, intBits, fracBits, maxValue) {\n const lsb = maxValue / (1 << fracBits);\n const min = -maxValue;\n const max = maxValue - lsb;\n let num = Math.min(Math.max(value, min), max);\n let encoded = Math.trunc(num * (1 << fracBits));\n const totalBits = 1 + intBits + fracBits;\n const mask = (1 << totalBits) - 1;\n return (encoded < 0) ? (encoded + (1 << totalBits)) & mask : encoded & mask;\n }\n static assembleInstruction(mnemonic, operands, schema) {\n let result = 0;\n let operandIdx = 0;\n for (const field of schema.fields) {\n let val = 0;\n if (field.value !== undefined) {\n val = field.value;\n }\n else {\n val = operands[operandIdx++];\n if (field.type)\n val = this.encode(field.type, val);\n }\n const mask = field.bits === 32 ? 0xFFFFFFFF : (1 << field.bits) - 1;\n result |= (val & mask) << field.offset;\n }\n return result >>> 0;\n }\n}\n//# sourceMappingURL=FV1Encoder.js.map","import { Lexer, Parser, ParserError } from './FV1Parser.js';\nimport { INSTRUCTION_SET, Encoder } from './FV1Encoder.js';\nexport class FV1Assembler {\n constructor(options = {}) {\n this.problems = [];\n this.symbols = new Map();\n this.memories = [];\n this.labels = new Map();\n this.addressToLineMap = new Map();\n this.usedRegisters = new Set();\n this.usedLFOs = new Set();\n this.configuredLFOs = new Set();\n this.userSymbols = new Set();\n this.symbolLines = new Map();\n this.PREDEFINED_SYMBOLS = {\n 'SIN0_RATE': 0x00, 'SIN0_RANGE': 0x01, 'SIN1_RATE': 0x02, 'SIN1_RANGE': 0x03,\n 'RMP0_RATE': 0x04, 'RMP0_RANGE': 0x05, 'RMP1_RATE': 0x06, 'RMP1_RANGE': 0x07,\n 'POT0': 0x10, 'POT1': 0x11, 'POT2': 0x12, 'ADCL': 0x14, 'ADCR': 0x15,\n 'DACL': 0x16, 'DACR': 0x17, 'ADDR_PTR': 0x18,\n 'SIN0': 0x00, 'SIN1': 0x01, 'RMP0': 0x02, 'RMP1': 0x03,\n 'COS0': 0x08, 'COS1': 0x09,\n 'RDA': 0x00, 'SOF': 0x02, 'RDAL': 0x03,\n 'SIN': 0x00, 'COS': 0x01, 'REG': 0x02, 'COMPC': 0x04,\n 'COMPA': 0x08, 'RPTR2': 0x10, 'NA': 0x20,\n 'RUN': 0x10, 'ZRC': 0x08, 'ZRO': 0x04,\n 'GEZ': 0x02, 'NEG': 0x01\n };\n this.reservedSymbols = new Set();\n this.options = {\n fv1AsmMemBug: options.fv1AsmMemBug ?? true,\n clampReals: options.clampReals ?? true,\n regCount: options.regCount ?? 32,\n progSize: options.progSize ?? 128,\n delaySize: options.delaySize ?? 32768\n };\n this.reset();\n }\n reset() {\n this.problems = [];\n this.symbols.clear();\n this.memories = [];\n this.labels.clear();\n this.addressToLineMap.clear();\n this.usedRegisters.clear();\n this.usedLFOs.clear();\n this.configuredLFOs.clear();\n this.userSymbols.clear();\n this.symbolLines.clear(); // Added this line\n this.initSymbols(); // Added this line\n }\n initSymbols() {\n // Load predefined symbols\n for (const [key, val] of Object.entries(this.PREDEFINED_SYMBOLS)) {\n this.symbols.set(key, val);\n this.reservedSymbols.add(key);\n }\n // Load REG0-31\n for (let i = 0; i < this.options.regCount; i++) {\n this.symbols.set(`REG${i}`, 0x20 + i);\n this.reservedSymbols.add(`REG${i}`);\n }\n }\n assemble(source) {\n this.reset();\n try {\n const lexer = new Lexer(source);\n const tokens = lexer.tokenize();\n const parser = new Parser(tokens);\n const ast = parser.parse();\n this.pass1_ResolveDirectives(ast);\n this.pass2_ResolveLabels(ast);\n const machineCode = this.pass3_GenerateCode(ast);\n return {\n machineCode,\n problems: this.problems,\n labels: this.labels,\n symbols: Array.from(this.symbols.entries())\n .filter(([name]) => this.userSymbols.has(name))\n .map(([name, value]) => ({ name, value: value.toString(), line: this.symbolLines.get(name) })),\n memories: this.memories,\n addressToLineMap: this.addressToLineMap,\n usedRegistersCount: this.usedRegisters.size,\n usedLFOs: Array.from(this.usedLFOs)\n };\n }\n catch (e) {\n const line = (e instanceof ParserError) ? e.line : 1;\n this.problems.push({ message: `Parser error: ${e instanceof Error ? e.message : String(e)}`, isfatal: true, line });\n return {\n machineCode: [],\n problems: this.problems,\n labels: new Map(),\n symbols: [],\n memories: [],\n addressToLineMap: new Map(),\n usedRegistersCount: 0,\n usedLFOs: []\n };\n }\n }\n pass1_ResolveDirectives(ast) {\n let nextDelayAddr = 0;\n for (const node of ast) {\n if (node.type === 'Directive') {\n if (node.name === 'EQU') {\n if (this.reservedSymbols.has(node.identifier)) {\n this.problems.push({ message: `Cannot redefine reserved symbol '${node.identifier}'`, isfatal: true, line: node.line });\n }\n else if (this.userSymbols.has(node.identifier)) {\n this.problems.push({ message: `Symbol '${node.identifier}' is already defined on line ${this.symbolLines.get(node.identifier)}`, isfatal: true, line: node.line });\n }\n else {\n const value = this.evaluateExpression(node.expression, node.line);\n this.symbols.set(node.identifier, value);\n this.userSymbols.add(node.identifier);\n this.symbolLines.set(node.identifier, node.line);\n }\n }\n else if (node.name === 'MEM') {\n if (this.reservedSymbols.has(node.identifier)) {\n this.problems.push({ message: `Cannot redefine reserved symbol '${node.identifier}'`, isfatal: true, line: node.line });\n continue;\n }\n const size = this.evaluateExpression(node.expression, node.line);\n const start = nextDelayAddr;\n const middle = start + (size % 2 ? (size - 1) / 2 - 1 : size / 2);\n const end = start + size - 1;\n const buggyEnd = end + (this.options.fv1AsmMemBug ? 1 : 0);\n const mem = { name: node.identifier, size, start, middle, end, line: node.line, original: '' };\n this.memories.push(mem);\n // Register special suffixes\n this.symbols.set(node.identifier, start);\n this.symbols.set(node.identifier + '^', middle);\n this.symbols.set(node.identifier + '#', buggyEnd);\n nextDelayAddr = buggyEnd + 1;\n }\n }\n }\n }\n pass2_ResolveLabels(ast) {\n let pc = 0;\n for (const node of ast) {\n if (node.type === 'Label') {\n this.labels.set(node.name, { line: node.line, instructionLine: pc });\n }\n else if (node.type === 'Instruction') {\n pc++;\n }\n }\n }\n pass3_GenerateCode(ast) {\n const code = [];\n let pc = 0;\n for (const node of ast) {\n if (node.type === 'Instruction') {\n const schema = INSTRUCTION_SET[node.mnemonic];\n if (!schema) {\n this.problems.push({ message: `Unknown instruction ${node.mnemonic}`, isfatal: true, line: node.line });\n code.push(0);\n continue;\n }\n let operands = node.operands.map(op => {\n // Special case for labels in JMP/SKP\n if (op.type === 'Identifier' && this.labels.has(op.name)) {\n return this.labels.get(op.name).instructionLine - pc - 1;\n }\n return this.evaluateExpression(op, node.line);\n });\n // --- Specialized Encoding Logic ---\n // LFO Tracking for configurations\n if (node.mnemonic === 'WLDS' || node.mnemonic === 'WLDR') {\n const lfoReg = operands[0];\n const lfoName = this.getLFOName(lfoReg);\n if (lfoName) {\n if (node.mnemonic === 'WLDS') {\n if (this.configuredLFOs.has(lfoName)) {\n this.problems.push({ message: `LFO ${lfoName} is configured more than once`, isfatal: true, line: node.line });\n }\n this.configuredLFOs.add(lfoName);\n }\n this.usedLFOs.add(lfoName);\n }\n }\n if (node.mnemonic === 'CHO') {\n const mode = operands[0];\n const n = operands[1];\n const rdaMode = this.symbols.get('RDA');\n const sofMode = this.symbols.get('SOF');\n const rdalMode = this.symbols.get('RDAL');\n if (mode === rdalMode) {\n // CHO RDAL, N -> [mode, flags=0x02(fixed bit 25), n, param=0]\n operands = [mode, 0x02, n, 0];\n }\n else if (mode === rdaMode || mode === sofMode) {\n const flags = operands[2];\n let param = operands[3];\n if (mode === sofMode) {\n param = Encoder.encode('S1_14', param);\n }\n operands = [mode, flags, n, param];\n }\n }\n else if (node.mnemonic === 'WLDR') {\n // Match previous backwards-encoded amplitude\n let ampl = operands[2];\n switch (ampl) {\n case 512:\n ampl = 3;\n break;\n case 1024:\n ampl = 2;\n break;\n case 2048:\n ampl = 1;\n break;\n case 4096:\n ampl = 0;\n break;\n default:\n this.problems.push({ message: `Invalid amplitude ${ampl} for WLDR`, isfatal: true, line: node.line });\n }\n // Handle RMP LFO mapping\n let rmpLfo = operands[0];\n if ([0, 2].includes(rmpLfo))\n rmpLfo = 0;\n else if ([1, 3].includes(rmpLfo))\n rmpLfo = 1;\n operands = [rmpLfo, operands[1], ampl];\n }\n else if (node.mnemonic === 'JAM') {\n let rmpLfo = operands[0];\n if ([0, 2].includes(rmpLfo))\n rmpLfo = 0;\n else if ([1, 3].includes(rmpLfo))\n rmpLfo = 1;\n operands = [rmpLfo];\n }\n // Track register usage\n schema.fields.forEach((field, i) => {\n if (field.type === 'REG' && operands[i] !== undefined) {\n this.trackRegister(operands[i], node.line);\n }\n });\n // Additional LFO tracking for register writes to RATE/RANGE\n if (node.mnemonic === 'WRAX' || node.mnemonic === 'RDAX') {\n const regNum = operands[0];\n const lfoName = this.getLFONameFromRegister(regNum);\n if (lfoName) {\n this.usedLFOs.add(lfoName);\n }\n }\n code.push(Encoder.assembleInstruction(node.mnemonic, operands, schema));\n this.addressToLineMap.set(pc, node.line);\n pc++;\n }\n }\n // Pad to progSize\n while (code.length < this.options.progSize)\n code.push(0x00000011); // NOP\n return code;\n }\n trackRegister(addr, line) {\n if (addr >= 0x20 && addr <= 0x3F) {\n const regNum = addr - 0x20;\n if (regNum >= this.options.regCount) {\n this.problems.push({ message: `Register REG${regNum} exceeds limit ${this.options.regCount}`, isfatal: true, line });\n }\n this.usedRegisters.add(regNum);\n }\n }\n getLFOName(lfoId) {\n switch (lfoId) {\n case 0: return 'SIN0';\n case 1: return 'SIN1';\n case 2: return 'RMP0';\n case 3: return 'RMP1';\n default: return null;\n }\n }\n getLFONameFromRegister(addr) {\n // 0x00=SIN0_RATE, 0x01=SIN0_RANGE, 0x02=SIN1_RATE, 0x03=SIN1_RANGE\n // 0x04=RMP0_RATE, 0x05=RMP0_RANGE, 0x06=RMP1_RATE, 0x07=RMP1_RANGE\n switch (addr) {\n case 0x00:\n case 0x01: return 'SIN0';\n case 0x02:\n case 0x03: return 'SIN1';\n case 0x04:\n case 0x05: return 'RMP0';\n case 0x06:\n case 0x07: return 'RMP1';\n default: return null;\n }\n }\n evaluateExpression(expr, line) {\n switch (expr.type) {\n case 'Number': return expr.value;\n case 'Identifier':\n if (this.symbols.has(expr.name))\n return this.symbols.get(expr.name);\n this.problems.push({ message: `Undefined symbol ${expr.name}`, isfatal: true, line });\n return 0;\n case 'Binary':\n const left = this.evaluateExpression(expr.left, line);\n const right = this.evaluateExpression(expr.right, line);\n switch (expr.operator) {\n case '+': return left + right;\n case '-': return left - right;\n case '*': return left * right;\n case '/': return left / right;\n case '|': return left | right;\n case '&': return left & right;\n case '^': return left ^ right;\n case '<': return (left << right) >>> 0;\n case '>': return (left >>> right);\n default: return 0;\n }\n case 'Unary':\n const val = this.evaluateExpression(expr.expression, line);\n if (expr.operator === '-')\n return -val;\n if (expr.operator === '!')\n return (~Math.floor(val)) >>> 0;\n return val;\n }\n }\n static formatMachineCode(machineCode) {\n return machineCode.map((word, index) => `${index.toString().padStart(4, '0')}\\t${word.toString(16).toUpperCase().padStart(8, '0')}`).join('\\n');\n }\n static toUint8Array(machineCode) {\n const buffer = new ArrayBuffer(machineCode.length * 4);\n const view = new DataView(buffer);\n machineCode.forEach((val, i) => view.setUint32(i * 4, val, false));\n return new Uint8Array(buffer);\n }\n static getMiddleAddr(start, size) {\n return start + (size % 2 ? (size - 1) / 2 - 1 : size / 2);\n }\n static getEndAddr(start, size, fv1AsmMemBug) {\n return start + size - 1 + (fv1AsmMemBug ? 1 : 0);\n }\n}\n//# sourceMappingURL=FV1Assembler.js.map","/**\n * FV-1 DSP Simulator\n *\n * Simulates the Spin Semiconductor FV-1 DSP chip.\n * This class is designed to be platform-agnostic (Node.js or Browser/AudioWorklet).\n */\nimport { FV1Assembler } from '../assembler/FV1Assembler.js';\nexport class FV1Simulator {\n // Register aliases (Getters/Setters)\n // 0-7: Parameters\n // These are now handled by updateStateRegisters for debugger view\n // 8-13: Internal State accumulators (aliased as registers for the debugger)\n // These are now handled by updateStateRegisters for debugger view\n constructor() {\n // Constants\n // Capabilities (Configurable)\n this.delaySize = 32768;\n this.delayMask = 32767; // For efficient circular buffer\n this.regCount = 32;\n this.progSize = 128;\n // --- Float-based LFO state (from Expert Sleepers C port) ---\n this.sin0 = 0;\n this.cos0 = 0;\n this.sin1 = 0;\n this.cos1 = 0;\n this.rmp0 = 0;\n this.rmp1 = 0;\n this.sin0_rate = 0;\n this.sin0_range = 0;\n this.sin1_rate = 0;\n this.sin1_range = 0;\n this.rmp0_rate = 0;\n this.rmp0_range = 0;\n this.rmp1_rate = 0;\n this.rmp1_range = 0;\n this.acc = 0;\n this.pacc = 0;\n this.lr = 0; // Last Read register\n this.lfo = 0; // Internal LFO fregister (for CHO)\n this.delayPointer = 0; // Circular buffer pointer\n this.firstRun = true;\n this.pc = 0; // Program Counter\n this.breakpoints = new Set();\n // Symbol metadata (optional, for debugging)\n this.symbols = [];\n this.memories = [];\n this.fv1AsmMemBug = false;\n // Pot input smoothing. Without this, an instantaneous slider step\n // can drive rate-sensitive control paths (e.g. the \"speedup\" lead-lag\n // filter on the pot block) into pathological overshoot that wouldn't\n // happen on real hardware where the pot moves continuously.\n this.potSmoothCoeff = 0; // 0 = disabled\n this.potSmoothed = [0.5, 0.5, 0.5];\n this.potSmoothInit = false;\n // --- Trace Logging ---\n this.traceEnabled = false;\n this.traceWriter = null; // Streaming callback\n this.cycleCount = 0;\n this.traceCycle = 0;\n this.traceMaxCycles = 0; // 0 = unlimited\n this.traceRowCount = 0;\n this.traceDelayAddr = -1; // computed physical address in delay RAM\n this.traceDelayOffset = -1; // raw offset from instruction (identifies MEM block)\n this.traceDelayOp = ''; // 'R' for read, 'W' for write\n this.traceDelayValue = 0; // value read/written\n this.traceInstructionPC = -1; // PC of currently executing instruction\n this.currentReadOffsets = new Set(); // Tracks read offsets in current sample cycle\n this.traceOnComplete = null;\n this.delayRam = new Float32Array(this.delaySize);\n this.registers = new Float32Array(32 + this.regCount);\n this.program = new Uint32Array(this.progSize);\n }\n /**\n * Configures simulator hardware limits.\n */\n setCapabilities(delaySize, regCount, progSize) {\n this.delaySize = delaySize;\n this.delayMask = delaySize - 1; // Assuming power of 2 for now, but modulo is fallback\n this.regCount = regCount; // Number of user registers\n this.progSize = progSize;\n // Reallocate if needed\n this.delayRam = new Float32Array(this.delaySize);\n this.registers = new Float32Array(32 + this.regCount); // 32 system + N user registers\n this.program = new Uint32Array(this.progSize);\n this.reset();\n }\n getDelayPointer() {\n return this.delayPointer;\n }\n getDelaySize() {\n return this.delaySize;\n }\n /**\n * Loads the machine code into the simulator.\n * @param code Array of 32-bit integers representing the assembled program.\n */\n loadProgram(code) {\n if (code.length > this.progSize) {\n console.warn(`Program size (${code.length}) exceeds max size (${this.progSize}). Truncating.`);\n }\n this.program.fill(0);\n this.program.set(code.slice(0, this.progSize));\n this.reset();\n }\n /**\n * Resets the simulator state (clears memory, registers, accumulator).\n */\n reset() {\n this.delayRam.fill(0);\n this.registers.fill(0);\n this.acc = 0;\n this.pacc = 0;\n this.lr = 0;\n this.lfo = 0;\n this.pc = 0;\n this.delayPointer = 0;\n this.firstRun = true;\n this.sin0 = 0;\n this.sin1 = 0;\n // Peak amplitude from Java SinLFO.java initialized to -0x7fff00 mapped to float (-1.0)\n // BUT wait, in C the initialization is not explicit, we can just use 1.0 or -1.0\n // SpinCAD sets cos to -0x7fff00l which is approx -1.0\n this.cos0 = -1.0;\n this.cos1 = -1.0;\n this.rmp0 = 0;\n this.rmp1 = 0;\n this.sin0_rate = 0;\n this.sin0_range = 0;\n this.sin1_rate = 0;\n this.sin1_range = 0;\n this.rmp0_rate = 0;\n this.rmp0_range = 0;\n this.rmp1_rate = 0;\n this.rmp1_range = 0;\n // Default POT values to 0.5\n this.registers[16] = 0.5;\n this.registers[17] = 0.5;\n this.registers[18] = 0.5;\n this.potSmoothed[0] = 0.5;\n this.potSmoothed[1] = 0.5;\n this.potSmoothed[2] = 0.5;\n this.potSmoothInit = false;\n }\n /**\n * Enable one-pole smoothing of the pot inputs to mimic a mechanical\n * pot's natural rate-limiting. The simulator otherwise accepts a\n * literal one-sample step on each pot, which can drive rate-sensitive\n * control paths (like the speedup lead-lag filter) into overshoot\n * that wouldn't occur on real hardware. Pass timeConstantSeconds <= 0\n * to disable.\n */\n setPotSmoothing(timeConstantSeconds, sampleRate) {\n if (timeConstantSeconds <= 0 || sampleRate <= 0) {\n this.potSmoothCoeff = 0;\n }\n else {\n this.potSmoothCoeff = 1 - Math.exp(-1 / (timeConstantSeconds * sampleRate));\n }\n }\n /**\n * Set breakpoints at specific instruction addresses.\n * @param addresses Set of addresses to break at.\n */\n setBreakpoints(addresses) {\n this.breakpoints = addresses;\n }\n /**\n * Set symbol and memory metadata for expression evaluation.\n */\n setSymbols(symbols, memories, fv1AsmMemBug = false) {\n this.symbols = symbols;\n this.memories = memories;\n this.fv1AsmMemBug = fv1AsmMemBug;\n }\n /**\n * Process a block of audio samples.\n * Useful for real-time audio processing in AudioWorklets.\n */\n processBlock(inputL, inputR, outputL, outputR, pot0, pot1, pot2) {\n const len = inputL.length;\n for (let i = 0; i < len; i++) {\n const [outL, outR] = this.step(inputL[i], inputR[i], pot0, pot1, pot2);\n outputL[i] = outL;\n outputR[i] = outR;\n }\n }\n /**\n * Process a single sample frame.\n * Executes instructions until the end of the program or a breakpoint is hit.\n * @param skipCurrentBreakpoint If true, will not break on the instruction at the current PC.\n * @returns [outL, outR, breakpointHit]\n */\n step(inL, inR, pot0, pot1, pot2, skipCurrentBreakpoint = false) {\n // Only begin a new frame if we are at PC 0 (either start or after wrap around)\n if (this.pc === 0) {\n this.beginFrame(inL, inR, pot0, pot1, pot2);\n }\n let firstInstruction = true;\n while (this.pc < this.progSize) {\n if (this.breakpoints.has(this.pc)) {\n if (!firstInstruction || !skipCurrentBreakpoint) {\n return [...this.getOutputs(), true];\n }\n }\n this.stepInstruction();\n firstInstruction = false;\n }\n return [...this.endFrame(), false];\n }\n getOutputs() {\n return [this.registers[22], this.registers[23]];\n }\n beginFrame(inL = 0, inR = 0, pot0 = 0, pot1 = 0, pot2 = 0) {\n this.cycleCount++;\n this.currentReadOffsets.clear();\n // Saturate inputs (ADC is -1.0 to 0.999..., POT is 0 to 0.999...)\n // POT has 10-bit resolution (1024 levels)\n const sat = (v) => Math.max(-1.0, Math.min(FV1Simulator.MAX_ACC, v));\n const satPot = (v) => {\n const quantized = Math.floor(Math.max(0, Math.min(0.9999999, v)) * 1024) / 1024;\n return quantized;\n };\n // Execute Program Setup\n this.acc = 0; // Accumulator is cleared at start of run\n this.lr = 0; // LR is transient\n this.pacc = 0;\n this.pc = 0;\n // Smooth pot inputs if enabled. Snap to the input on the first\n // frame after reset so loaded preset values are heard immediately\n // rather than ramping from the 0.5 default.\n if (this.potSmoothCoeff > 0) {\n if (!this.potSmoothInit) {\n this.potSmoothed[0] = pot0;\n this.potSmoothed[1] = pot1;\n this.potSmoothed[2] = pot2;\n this.potSmoothInit = true;\n }\n else {\n this.potSmoothed[0] += (pot0 - this.potSmoothed[0]) * this.potSmoothCoeff;\n this.potSmoothed[1] += (pot1 - this.potSmoothed[1]) * this.potSmoothCoeff;\n this.potSmoothed[2] += (pot2 - this.potSmoothed[2]) * this.potSmoothCoeff;\n }\n pot0 = this.potSmoothed[0];\n pot1 = this.potSmoothed[1];\n pot2 = this.potSmoothed[2];\n }\n // Map inputs to registers (Standard FV-1 mapping)\n this.registers[20] = sat(inL);\n this.registers[21] = sat(inR);\n this.registers[16] = satPot(pot0);\n this.registers[17] = satPot(pot1);\n this.registers[18] = satPot(pot2);\n this.updateStateRegisters();\n }\n endFrame() {\n this.pc = 0;\n this.firstRun = false;\n this.updateLFOs();\n this.updateStateRegisters();\n this.advanceTraceCycle();\n // Advance Delay Pointer (Circular Buffer)\n this.delayPointer = (this.delayPointer - 1 + this.delaySize) % this.delaySize;\n // Outputs (DACL = REG22, DACR = REG23)\n return [this.registers[22], this.registers[23]];\n }\n /**\n * Executes a single instruction at the current PC.\n * @returns The next PC address.\n */\n stepInstruction() {\n if (this.pc >= this.progSize)\n return this.pc;\n const inst = this.program[this.pc];\n const opcode = inst & 0x1F;\n const preOpAcc = this.acc;\n // Reset per-instruction trace state\n this.traceDelayAddr = -1;\n this.traceDelayOffset = -1;\n this.traceDelayOp = '';\n this.traceDelayValue = 0;\n this.traceInstructionPC = this.pc;\n const skip = this.executeInstruction(inst);\n // Trace log AFTER instruction executes so ACC reflects the result\n if (this.traceEnabled) {\n this.logTrace(this.traceInstructionPC, opcode, inst, preOpAcc);\n }\n if (opcode !== 0x11) { // Not SKP\n this.pacc = preOpAcc;\n }\n this.pc += 1 + skip;\n return this.pc;\n }\n executeInstruction(inst) {\n const opcode = inst & 0x1F; // Bottom 5 bits for opcode\n let skip = 0;\n switch (opcode) {\n case 0x00: // RDA (Read Delay Accumulate)\n this.opRDA(inst);\n break;\n case 0x01: // RMPA (Read Memory Pointer Accumulate)\n this.opRMPA(inst);\n break;\n case 0x02: // WRA (Write Delay Accumulate)\n this.opWRA(inst);\n break;\n case 0x03: // WRAP (Write Delay Accumulate & Pointer)\n this.opWRAP(inst);\n break;\n case 0x04: // RDAX (Read Register Accumulate)\n this.opRDAX(inst);\n break;\n case 0x05: // RDFX (Read Register Filter)\n this.opRDFX(inst);\n break;\n case 0x06: // WRAX (Write Register Accumulate)\n this.opWRAX(inst);\n break;\n case 0x07: // WRHX (Write Register High)\n this.opWRHX(inst);\n break;\n case 0x08: // WRLX (Write Register Low)\n this.opWRLX(inst);\n break;\n case 0x09: // MAXX\n this.opMAXX(inst);\n break;\n case 0x0A: // MULX\n this.opMULX(inst);\n break;\n case 0x0B: // LOG\n this.opLOG(inst);\n break;\n case 0x0C: // EXP\n this.opEXP(inst);\n break;\n case 0x0D: // SOF\n this.opSOF(inst);\n break;\n case 0x0E: // AND\n this.opAND(inst);\n break;\n case 0x0F: // OR\n this.opOR(inst);\n break;\n case 0x10: // XOR\n this.opXOR(inst);\n break;\n case 0x11: // SKP\n skip = this.opSKP(inst);\n break;\n case 0x12: // WLDS / WLDR\n // Check bit 30 to distinguish WLDS (0) and WLDR (1)\n if ((inst >>> 30) & 1) {\n this.opWLDR(inst);\n }\n else {\n this.opWLDS(inst);\n }\n break;\n case 0x13: // JAM\n this.opJAM(inst);\n break;\n case 0x14: // CHO\n this.opCHO(inst);\n break;\n default:\n // console.warn(`Unknown opcode: ${opcode.toString(16)}`);\n break;\n }\n return skip;\n }\n // --- Opcode Implementations ---\n opRDA(inst) {\n // ... (existing comments)\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n // Address is relative to current delay pointer in circular buffer\n const readAddr = (this.delayPointer + addr) & this.delayMask;\n const val = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'R';\n this.traceDelayValue = val;\n this.currentReadOffsets.add(addr);\n this.lr = val;\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRA(inst) {\n // WRA addr, coeff\n // Delay[addr] = ACC; ACC = ACC * coeff\n // Encoding: CCCCCCCCCCCAAAAAAAAAAAAAAAA00010\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n const writeAddr = (this.delayPointer + addr) & this.delayMask;\n this.traceDelayAddr = writeAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'W';\n this.traceDelayValue = this.acc;\n this.delayRam[writeAddr] = this.acc;\n this.acc *= coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRAP(inst) {\n // WRAP addr, coeff\n // Delay[addr] = ACC; ACC = ACC * coeff + LR\n // Note: Pointer decrement happens at end of step, not here.\n // Encoding: CCCCCCCCCCCAAAAAAAAAAAAAAAA00011\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n const writeAddr = (this.delayPointer + addr) & this.delayMask;\n this.traceDelayAddr = writeAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'W';\n this.traceDelayValue = this.acc;\n this.delayRam[writeAddr] = this.acc;\n // ACC = ACC * coeff + LR\n this.acc = this.acc * coeff + this.lr;\n this.acc = this.saturate(this.acc);\n }\n opRDAX(inst) {\n // RDAX reg, coeff\n // ACC = ACC + (Reg[reg] * coeff)\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00100\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const val = this.registers[reg];\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRAX(inst) {\n // WRAX reg, coeff\n // Reg[reg] = ACC; ACC = ACC * coeff\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00110\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc *= coeff;\n this.acc = this.saturate(this.acc);\n }\n opSOF(inst) {\n // SOF c, d\n // ACC = ACC * c + d\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01101\n const d = this.decodeS_10((inst >>> 5) & 0x7FF);\n const c = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.acc = this.acc * c + d;\n this.acc = this.saturate(this.acc);\n }\n opRMPA(inst) {\n // RMPA coeff\n // Read memory pointer. ADDR_PTR is mapped to REG24.\n // Encoding: CCCCCCCCCCC000000000001100000001 (or similar, coeff is top)\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n const ptr = Math.floor(this.registers[24] * this.delaySize);\n const readAddr = (this.delayPointer + ptr) & this.delayMask;\n const val = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = ptr;\n this.traceDelayOp = 'R';\n this.traceDelayValue = val;\n this.currentReadOffsets.add(ptr);\n this.lr = val;\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opMULX(inst) {\n // Encoding: 000000000000000000000AAAAAA01010\n const reg = (inst >>> 5) & 0x3F;\n this.acc = this.acc * this.registers[reg];\n this.acc = this.saturate(this.acc);\n }\n opLOG(inst) {\n // ACC = log2(|ACC|) * coeff + d\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01011\n const d = this.decodeS4_6((inst >>> 5) & 0x7FF);\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const val = Math.abs(this.acc);\n let logVal;\n if (val > 1.52587890625e-5) { // 2^-16, approx 96dB limit\n logVal = Math.log2(val);\n }\n else {\n logVal = -16.0;\n }\n // Result is in S4.19 format, so we divide by 16 to keep it in our S.23 float space\n this.acc = (logVal * coeff + d) / 16.0;\n this.acc = this.saturate(this.acc);\n }\n opEXP(inst) {\n // ACC = 2^ACC\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01100\n const d = this.decodeS_10((inst >>> 5) & 0x7FF);\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const valS419 = this.acc * 16.0;\n // Result is linear S.23, which naturally fits our -1..1 float range\n this.acc = Math.pow(2, valS419) * coeff + d;\n this.acc = this.saturate(this.acc);\n }\n opRDFX(inst) {\n // RDFX reg, coeff\n // ACC = (REG[reg] - ACC) * coeff + REG[reg]\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00101\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const rx = this.registers[reg];\n this.acc = (this.acc - rx) * coeff + rx;\n this.acc = this.saturate(this.acc);\n }\n opMAXX(inst) {\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA01001\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const a = Math.abs(this.acc);\n const b = Math.abs(this.registers[reg] * coeff);\n // MAXX result is always the magnitude (absolute value)\n this.acc = Math.max(a, b);\n this.acc = this.saturate(this.acc);\n }\n opSKP(inst) {\n // SKP condition, n\n // Encoding: CCCCCNNNNNN000000000000000010001\n const n = (inst >>> 21) & 0x3F;\n const flags = inst & 0xF8000000;\n let conditionMet = false;\n // Flags: RUN=0x80000000, ZRC=0x40000000, ZRO=0x20000000, GEZ=0x10000000, NEG=0x08000000\n if ((flags & 0x08000000) && this.acc < 0)\n conditionMet = true; // NEG\n if ((flags & 0x10000000) && this.acc >= 0)\n conditionMet = true; // GEZ\n if ((flags & 0x20000000) && this.acc === 0)\n conditionMet = true; // ZRO\n // ZRC (Zero Crossing) requires previous acc\n if ((flags & 0x40000000) && (this.acc * this.pacc < 0))\n conditionMet = true;\n // RUN flag: Skip if NOT first run\n if ((flags & 0x80000000) && !this.firstRun)\n conditionMet = true;\n return conditionMet ? n : 0;\n }\n opWRLX(inst) {\n // WRLX reg, coeff\n // Reg[reg] = ACC; ACC = (PACC - ACC) * coeff + PACC\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA01000\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc = (this.pacc - this.acc) * coeff + this.pacc;\n this.acc = this.saturate(this.acc);\n }\n opWRHX(inst) {\n // WRHX reg, coeff\n // Reg[reg] = ACC; ACC = PACC + ACC * coeff\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00111\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc = this.pacc + this.acc * coeff;\n this.acc = this.saturate(this.acc);\n }\n opAND(inst) {\n // AND mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00001110\n const mask = (inst >>> 8) & 0xFFFFFF;\n // Convert ACC to 24-bit int, apply mask, convert back\n let iAcc = Math.floor(this.acc * 8388608.0); // 2^23\n iAcc &= mask;\n this.acc = iAcc / 8388608.0;\n }\n opOR(inst) {\n // OR mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00001111\n const mask = (inst >>> 8) & 0xFFFFFF;\n let iAcc = Math.floor(this.acc * 8388608.0);\n iAcc |= mask;\n this.acc = iAcc / 8388608.0;\n }\n opXOR(inst) {\n // XOR mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00010000\n const mask = (inst >>> 8) & 0xFFFFFF;\n let iAcc = Math.floor(this.acc * 8388608.0);\n iAcc ^= mask;\n this.acc = iAcc / 8388608.0;\n }\n opJAM(inst) {\n // JAM lfo\n // Encoding: 0000000000000000000000001N010011\n const lfo = (inst >>> 6) & 0x3; // 0=RMP0, 1=RMP1\n if (lfo === 0)\n this.rmp0 = 0;\n else if (lfo === 1)\n this.rmp1 = 0;\n }\n opWLDS(inst) {\n // WLDS lfo, freq, amp\n const lfoSelect = (inst >>> 29) & 0x1;\n const freqRaw = (inst >>> 20) & 0x1FF;\n const ampRaw = (inst >>> 5) & 0x7FFF;\n // Freq is an unsigned 9-bit value (0 to 511), amp is unsigned 15-bit (0 to 32767).\n // The FV-1 hardware uses power-of-2 fixed-point arithmetic (bit shifts),\n // so amplitude is divided by 2^15=32768, not 32767. Using 32767 causes the\n // computed delay address range to slightly exceed memory block boundaries.\n const f = freqRaw / 512.0;\n const a = ampRaw / 32768.0;\n if (lfoSelect === 0) {\n this.sin0_rate = f;\n this.sin0_range = a;\n this.registers[0] = f; // SIN0_RATE (reg0)\n this.registers[1] = a; // SIN0_RANGE (reg1)\n this.cos0 = -1.0;\n this.sin0 = 0.0;\n }\n else {\n this.sin1_rate = f;\n this.sin1_range = a;\n this.registers[2] = f; // SIN1_RATE (reg2)\n this.registers[3] = a; // SIN1_RANGE (reg3)\n this.cos1 = -1.0;\n this.sin1 = 0.0;\n }\n }\n opWLDR(inst) {\n // WLDR lfo, freq, amp\n // Encoding: 01NFFFFFFFFFFFFFFFF000000AA10010\n const lfoSelect = (inst >>> 29) & 0x1; // 0=RMP0, 1=RMP1\n // Freq is signed 16-bit\n let freq = (inst >>> 13) & 0xFFFF;\n if (freq & 0x8000)\n freq -= 65536;\n // Amp is a 2-bit code\n const ampCode = (inst >>> 5) & 0x3;\n const amp = 4096 >> ampCode; // 0->4096, 1->2048, 2->1024, 3->512\n // C logic: rate = f/16384.0, range = a/8192.0\n const f_val = freq / 16384.0;\n const a_val = amp / 8192.0;\n if (lfoSelect === 0) {\n this.rmp0_rate = f_val;\n this.rmp0_range = a_val;\n this.registers[4] = f_val; // RMP0_RATE (reg4)\n this.registers[5] = a_val; // RMP0_RANGE (reg5)\n this.rmp0 = 0.0;\n }\n else {\n this.rmp1_rate = f_val;\n this.rmp1_range = a_val;\n this.registers[6] = f_val; // RMP1_RATE (reg6)\n this.registers[7] = a_val; // RMP1_RANGE (reg7)\n this.rmp1 = 0.0;\n }\n }\n getLfoVal(flags, lfoSelect) {\n if (lfoSelect === 0) {\n return (flags & 1) ? this.cos0 : this.sin0;\n }\n else if (lfoSelect === 1) {\n return (flags & 1) ? this.cos1 : this.sin1;\n }\n else if (lfoSelect === 2) {\n return this.rmp0;\n }\n else {\n return this.rmp1;\n }\n }\n getLfoRange(lfoSelect) {\n if (lfoSelect === 0)\n return this.sin0_range;\n if (lfoSelect === 1)\n return this.sin1_range;\n if (lfoSelect === 2)\n return this.rmp0_range;\n return this.rmp1_range;\n }\n opCHO(inst) {\n const mode = (inst >>> 30) & 0x3;\n if (mode === 0) {\n this.opCHO_RDA(inst);\n }\n else if (mode === 2) {\n this.opCHO_SOF(inst);\n }\n else if (mode === 3) {\n this.opCHO_RDAL(inst);\n }\n }\n opCHO_RDA(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const offset = (inst >>> 5) & 0x7FFF;\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n let range = this.getLfoRange(lfoSelect);\n range *= 8192.0;\n if (flags & 2) { // cho_reg\n this.lfo = lfoIn;\n }\n let v = this.lfo;\n if (flags & 16) { // cho_rptr2\n v += 0.5;\n if (v >= 1.0)\n v -= 1.0;\n }\n if (flags & 8) { // cho_compa\n v = -v;\n }\n let index;\n let c;\n if (flags & 32) { // cho_na\n index = offset;\n c = Math.min(v, 1.0 - v);\n c = Math.max(0.0, Math.min(1.0, 4.0 * c - 0.5));\n }\n else {\n // Match the FV-1 / reference C: combine v*range with offset BEFORE\n // flooring. Separating them (e.g. trunc(v*range) + offset) gives the\n // wrong integer index when v*range is negative, because Math.trunc\n // rounds toward zero. Linear interpolation needs floor semantics.\n const addr = v * range + offset;\n index = Math.floor(addr);\n c = addr - index;\n }\n const readAddr = (this.delayPointer + index) & this.delayMask;\n this.lr = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = index;\n this.traceDelayOp = 'R';\n this.traceDelayValue = this.lr;\n this.currentReadOffsets.add(index);\n if (flags & 4) { // cho_compc\n c = 1.0 - c;\n }\n this.acc += this.lr * c;\n this.acc = this.saturate(this.acc);\n }\n opCHO_SOF(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const coeffRaw = (inst >>> 5) & 0xFFFF;\n const coeff = this.decodeS_15(coeffRaw);\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n const range = this.getLfoRange(lfoSelect);\n if (flags & 2) { // cho_reg\n this.lfo = lfoIn;\n }\n let v = this.lfo;\n if (flags & 32) { // cho_na\n v = Math.min(v, 1.0 - v);\n v = Math.max(0.0, Math.min(1.0, 4.0 * v - 0.5));\n }\n else {\n v *= range;\n }\n if (flags & 4) { // cho_compc\n v = 1.0 - v;\n }\n this.acc = v * this.acc + coeff;\n this.acc = this.saturate(this.acc);\n }\n opCHO_RDAL(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n this.acc = lfoIn;\n this.acc = this.saturate(this.acc);\n }\n // --- Debugging / State Access ---\n getPC() {\n return this.pc;\n }\n getProgSize() {\n return this.progSize;\n }\n setPC(pc) {\n this.pc = Math.max(0, Math.min(this.progSize - 1, pc));\n }\n setAcc(val) {\n this.acc = this.saturate(val);\n }\n setPacc(val) {\n this.pacc = this.saturate(val);\n }\n /**\n * Sets a register value with hardware-accurate saturation and quantization.\n * @param idx Register index (0-63)\n * @param val Raw value (float)\n */\n setRegister(idx, val) {\n if (idx < 0 || idx >= (32 + this.regCount))\n return;\n // POT registers (16, 17, 18) are 10-bit quantized 0..1\n if (idx >= 16 && idx <= 18) {\n val = Math.floor(Math.max(0, Math.min(0.9999999, val)) * 1024) / 1024;\n }\n else {\n // Other registers (ADC, DAC, User) are S.23 saturated\n val = this.saturate(val);\n }\n this.registers[idx] = val;\n }\n /**\n * Evaluates a string expression (register name, symbol, memory suffix).\n * @returns { result: string, value: number } or null\n */\n evaluateExpression(expr) {\n let expression = expr.trim().toUpperCase();\n // Handle suffixes ^ and #\n let suffix = \"\";\n if (expression.endsWith(\"^\")) {\n suffix = \"^\";\n expression = expression.slice(0, -1);\n }\n else if (expression.endsWith(\"#\")) {\n suffix = \"#\";\n expression = expression.slice(0, -1);\n }\n // 1. Check if it's a register name\n const state = this.getState();\n if (suffix === \"\" && state.registers[expression] !== undefined) {\n return { label: expression, value: state.registers[expression] };\n }\n // 2. Check if it's ACC/PACC\n if (suffix === \"\" && expression === \"ACC\") {\n return { label: \"ACC\", value: this.acc };\n }\n if (suffix === \"\" && expression === \"PACC\") {\n return { label: \"PACC\", value: this.pacc };\n }\n // 3. Check symbols (EQU)\n const sym = this.symbols.find(s => s.name.toUpperCase() === expression);\n if (sym && suffix === \"\") {\n const addr = parseInt(sym.value);\n if (!isNaN(addr) && addr >= 0 && addr <= 63) {\n return { label: `REG[${addr}] (${sym.name})`, value: this.registers[addr] };\n }\n }\n // 4. Check memories (MEM)\n const mem = this.memories.find(m => m.name.toUpperCase() === expression);\n if (mem && mem.start !== undefined) {\n let addr = mem.start;\n let typeLabel = \"\";\n if (suffix === \"^\") {\n addr = FV1Assembler.getMiddleAddr(mem.start, mem.size);\n typeLabel = \" (Middle)\";\n }\n else if (suffix === \"#\") {\n addr = FV1Assembler.getEndAddr(mem.start, mem.size, this.fv1AsmMemBug);\n typeLabel = \" (End)\";\n }\n if (addr >= 0 && addr < this.delaySize) {\n return { label: `MEM[${addr}] (${mem.name}${typeLabel})`, value: this.delayRam[addr] };\n }\n }\n // 5. Check DELAY[idx]\n if (suffix === \"\") {\n const delayMatch = expression.match(/^DELAY\\[(\\d+)\\]$/);\n if (delayMatch) {\n const idx = parseInt(delayMatch[1]);\n if (idx >= 0 && idx < this.delaySize) {\n return { label: `DELAY[${idx}]`, value: this.delayRam[idx] };\n }\n }\n }\n return null;\n }\n getState() {\n return {\n pc: this.pc,\n acc: this.acc,\n pacc: this.pacc,\n lr: this.lr,\n lfo: this.lfo,\n // Official Register Naming\n registers: Object.fromEntries(Array.from({ length: 32 + this.regCount }, (_, i) => {\n let name = `[${i}]`;\n if (i === 0)\n name = \"SIN0_RATE\";\n else if (i === 1)\n name = \"SIN0_RANGE\";\n else if (i === 2)\n name = \"SIN1_RATE\";\n else if (i === 3)\n name = \"SIN1_RANGE\";\n else if (i === 4)\n name = \"RMP0_RATE\";\n else if (i === 5)\n name = \"RMP0_RANGE\";\n else if (i === 6)\n name = \"RMP1_RATE\";\n else if (i === 7)\n name = \"RMP1_RANGE\";\n else if (i === 8)\n name = \"SIN0\";\n else if (i === 9)\n name = \"COS0\";\n else if (i === 10)\n name = \"SIN1\";\n else if (i === 11)\n name = \"COS1\";\n else if (i === 12)\n name = \"RMP0\";\n else if (i === 13)\n name = \"RMP1\";\n else if (i === 16)\n name = \"POT0\";\n else if (i === 17)\n name = \"POT1\";\n else if (i === 18)\n name = \"POT2\";\n else if (i === 20)\n name = \"ADCL\";\n else if (i === 21)\n name = \"ADCR\";\n else if (i === 22)\n name = \"DACL\";\n else if (i === 23)\n name = \"DACR\";\n else if (i === 24)\n name = \"ADDR_PTR\";\n else if (i >= 32 && i <= 63)\n name = `REG${i - 32}`;\n return [name, this.registers[i]];\n })),\n // Flags\n flags: {\n RUN: this.firstRun,\n ZRC: (this.acc * this.pacc < 0),\n ZRO: (this.acc === 0),\n GEZ: (this.acc >= 0),\n NEG: (this.acc < 0)\n },\n // LFO Internal positions\n lfoState: {\n sin0: this.sin0, cos0: this.cos0,\n sin1: this.sin1, cos1: this.cos1,\n rmp0: this.rmp0, rmp1: this.rmp1\n }\n };\n }\n getCycleCount() {\n return this.cycleCount;\n }\n getReadOffsets() {\n return Array.from(this.currentReadOffsets);\n }\n getRegisters() {\n return this.registers;\n }\n updateLFOs() {\n // Sync internal LFO modulations explicitly modified by WRAX or WRHX\n this.sin0_rate = this.registers[0];\n this.sin0_range = this.registers[1];\n this.sin1_rate = this.registers[2];\n this.sin1_range = this.registers[3];\n this.rmp0_rate = this.registers[4];\n this.rmp0_range = this.registers[5];\n this.rmp1_rate = this.registers[6];\n this.rmp1_range = this.registers[7];\n // C logic update_rmp0/1\n this.rmp0 -= this.rmp0_rate * (1.0 / 4096.0);\n while (this.rmp0 >= 1.0)\n this.rmp0 -= 1.0;\n while (this.rmp0 < 0.0)\n this.rmp0 += 1.0;\n this.rmp1 -= this.rmp1_rate * (1.0 / 4096.0);\n while (this.rmp1 >= 1.0)\n this.rmp1 -= 1.0;\n while (this.rmp1 < 0.0)\n this.rmp1 += 1.0;\n // SIN LFO update using coupled-form oscillator.\n // The FV-1 hardware updates cos first, then uses the updated cos for sin.\n // Clamp to [-1.0, MAX_ACC] to prevent float drift from exceeding the\n // FV-1's 24-bit fixed-point register range.\n const x0 = this.sin0_rate * (1.0 / 256.0);\n this.cos0 += x0 * this.sin0;\n this.sin0 -= x0 * this.cos0;\n this.sin0 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.sin0));\n this.cos0 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.cos0));\n const x1 = this.sin1_rate * (1.0 / 256.0);\n this.cos1 += x1 * this.sin1;\n this.sin1 -= x1 * this.cos1;\n this.sin1 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.sin1));\n this.cos1 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.cos1));\n }\n updateStateRegisters() {\n // ONLY update accumulators here! Rate/Range is dictated by the program loop!\n // Writing registers[0..7] here would explicitly overwrite mid-frame WRAX modulations!\n // LFO State Accumulators\n this.registers[8] = this.sin0;\n this.registers[9] = this.cos0;\n this.registers[10] = this.sin1;\n this.registers[11] = this.cos1;\n this.registers[12] = this.rmp0;\n this.registers[13] = this.rmp1;\n }\n getDelayRam() {\n return this.delayRam;\n }\n // --- Helpers ---\n decodeS1_14(raw) {\n // 16 bits: 1 sign, 1 integer, 14 fractional\n if (raw & 0x8000)\n return (raw - 0x10000) / 16384.0;\n return raw / 16384.0;\n }\n decodeS1_9(raw) {\n // 11 bits: 1 sign, 1 integer, 9 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 512.0;\n return raw / 512.0;\n }\n decodeS_10(raw) {\n // 11 bits: 1 sign, 0 integer, 10 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 1024.0;\n return raw / 1024.0;\n }\n decodeS4_6(raw) {\n // 11 bits: 1 sign, 4 integer, 6 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 64.0;\n return raw / 64.0;\n }\n decodeS_15(raw) {\n // 16 bits: 1 sign, 0 integer, 15 fractional\n if (raw & 0x8000)\n return (raw - 0x10000) / 32768.0;\n return raw / 32768.0;\n }\n saturate(val) {\n if (val > FV1Simulator.MAX_ACC)\n return FV1Simulator.MAX_ACC;\n if (val < FV1Simulator.MIN_ACC)\n return FV1Simulator.MIN_ACC;\n return val;\n }\n /**\n * Enable trace logging with a streaming writer callback.\n * Each row is emitted immediately via the writer — nothing is stored in memory.\n * @param writer Callback that receives each CSV row (including header).\n * @param maxCycles Maximum number of sample cycles to log (0 = unlimited).\n * @param onComplete Optional callback when trace auto-completes.\n */\n enableTrace(writer, maxCycles = 0, onComplete) {\n this.traceEnabled = true;\n this.traceWriter = writer;\n this.traceMaxCycles = maxCycles;\n this.traceCycle = 0;\n this.traceRowCount = 0;\n this.traceOnComplete = onComplete || null;\n // Emit CSV Header immediately (Reduced set for delay debugging)\n writer(`cycle,pc,opcode,delay_op,delay_offset,delay_addr,delay_ptr`);\n console.log(`[FV1 Trace] Logging enabled (maxCycles=${maxCycles || 'unlimited'})`);\n }\n /**\n * Disable trace logging.\n */\n disableTrace() {\n this.traceEnabled = false;\n this.traceWriter = null;\n console.log(`[FV1 Trace] Logging disabled. ${this.traceRowCount} rows written.`);\n }\n /**\n * Returns whether trace logging is currently active.\n */\n isTraceEnabled() {\n return this.traceEnabled;\n }\n /**\n * Returns the number of trace rows emitted so far.\n */\n getTraceRowCount() {\n return this.traceRowCount;\n }\n /**\n * Called at end-of-frame to advance the trace cycle counter.\n * If maxCycles is reached, trace is automatically disabled.\n */\n advanceTraceCycle() {\n if (!this.traceEnabled)\n return;\n this.traceCycle++;\n if (this.traceMaxCycles > 0 && this.traceCycle >= this.traceMaxCycles) {\n const onComplete = this.traceOnComplete;\n this.disableTrace();\n if (onComplete)\n onComplete();\n }\n }\n logTrace(pc, opcode, inst, accBefore) {\n if (!this.traceWriter)\n return;\n // FILTER: Only log delay memory operations\n if (this.traceDelayOp === '')\n return;\n const opName = FV1Simulator.OPCODE_NAMES[opcode] || `?${opcode.toString(16)}`;\n // Resolve CHO sub-type\n let fullOpName = opName;\n if (opcode === 0x14) {\n const mode = (inst >>> 30) & 0x3;\n if (mode === 0)\n fullOpName = 'CHO_RDA';\n else if (mode === 2) {\n // CHO_SOF does not access delay RAM, so we filter it out\n return;\n }\n else if (mode === 3)\n fullOpName = 'CHO_RDAL';\n }\n else if (opcode === 0x12) {\n // WLDS/WLDR do not access delay RAM directly in a way we track here\n return;\n }\n const row = `${this.traceCycle},${pc},${fullOpName},` +\n `${this.traceDelayOp},${this.traceDelayOp !== '' ? this.traceDelayOffset : ''},${this.traceDelayAddr >= 0 ? this.traceDelayAddr : ''},${this.delayPointer}`;\n this.traceWriter(row);\n this.traceRowCount++;\n }\n}\nFV1Simulator.MAX_ACC = 1.0 - (1.0 / 8388608.0); // 24-bit S.23: 1 - 2^-23\nFV1Simulator.MIN_ACC = -FV1Simulator.MAX_ACC; // Symmetrically bound to prevent limits bias\n// --- Trace Logging System ---\nFV1Simulator.OPCODE_NAMES = {\n 0x00: 'RDA', 0x01: 'RMPA', 0x02: 'WRA', 0x03: 'WRAP',\n 0x04: 'RDAX', 0x05: 'RDFX', 0x06: 'WRAX', 0x07: 'WRHX',\n 0x08: 'WRLX', 0x09: 'MAXX', 0x0A: 'MULX', 0x0B: 'LOG',\n 0x0C: 'EXP', 0x0D: 'SOF', 0x0E: 'AND', 0x0F: 'OR',\n 0x10: 'XOR', 0x11: 'SKP', 0x12: 'WLDx', 0x13: 'JAM',\n 0x14: 'CHO'\n};\n//# sourceMappingURL=FV1Simulator.js.map","import { FV1Simulator } from '@audiofab-io/fv1-core'\n\ntype ChannelMode = 'mono' | 'stereo'\n\nclass FV1Processor extends AudioWorkletProcessor {\n private simulator = new FV1Simulator()\n private pot = [0.5, 0.5, 0.5]\n private bypassed = false\n /** Mono emulates the current Easy Spin hardware (only the left DAC is wired\n * to both jack tips). Stereo plays the FV-1's native left/right outputs. */\n private channelMode: ChannelMode = 'mono'\n\n constructor() {\n super()\n // Smooth pot inputs to approximate a mechanical pot's rate-limited\n // travel. A literal one-sample slider step otherwise drives the\n // pot block's \"speedup\" lead-lag filter into overshoot.\n this.simulator.setPotSmoothing(0.030, sampleRate)\n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case 'loadProgram':\n this.simulator.loadProgram(new Uint32Array(data.machineCode))\n break\n case 'setPot':\n this.pot[data.index] = data.value\n break\n case 'bypass':\n this.bypassed = data.active\n break\n case 'setChannelMode':\n this.channelMode = data.mode === 'stereo' ? 'stereo' : 'mono'\n break\n }\n }\n }\n\n process(inputs: Float32Array[][], outputs: Float32Array[][]): boolean {\n const input = inputs[0]\n const output = outputs[0]\n if (!input?.length || !output?.length) return true\n\n const inL = input[0]\n const inR = input[1] ?? inL\n const outL = output[0]\n const outR = output[1] ?? outL\n\n if (this.bypassed) {\n outL.set(inL)\n if (output[1]) outR.set(inR)\n return true\n }\n\n this.simulator.processBlock(inL, inR, outL, outR,\n this.pot[0], this.pot[1], this.pot[2])\n\n // Mono: mirror the left (FV-1 DACL) output to the right channel so the\n // simulator matches the current mono pedal, where only DACL drives the jack.\n if (this.channelMode === 'mono' && output[1]) {\n outR.set(outL)\n }\n return true\n }\n}\n\nregisterProcessor('fv1-processor', FV1Processor)\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fv1-processor.js","names":[],"sources":["../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Parser.js","../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Encoder.js","../../node_modules/@audiofab-io/fv1-core/dist/assembler/FV1Assembler.js","../../node_modules/@audiofab-io/fv1-core/dist/simulator/FV1Simulator.js","../../src/worklet/fv1-processor.ts"],"sourcesContent":["export class ParserError extends Error {\n constructor(message, line, column) {\n super(message);\n this.line = line;\n this.column = column;\n this.name = 'ParserError';\n }\n}\nexport var TokenType;\n(function (TokenType) {\n TokenType[TokenType[\"IDENTIFIER\"] = 0] = \"IDENTIFIER\";\n TokenType[TokenType[\"NUMBER\"] = 1] = \"NUMBER\";\n TokenType[TokenType[\"MNEMONIC\"] = 2] = \"MNEMONIC\";\n TokenType[TokenType[\"DIRECTIVE\"] = 3] = \"DIRECTIVE\";\n TokenType[TokenType[\"OPERATOR\"] = 4] = \"OPERATOR\";\n TokenType[TokenType[\"COMMA\"] = 5] = \"COMMA\";\n TokenType[TokenType[\"COLON\"] = 6] = \"COLON\";\n TokenType[TokenType[\"NEWLINE\"] = 7] = \"NEWLINE\";\n TokenType[TokenType[\"EOF\"] = 8] = \"EOF\";\n TokenType[TokenType[\"LPAREN\"] = 9] = \"LPAREN\";\n TokenType[TokenType[\"RPAREN\"] = 10] = \"RPAREN\";\n})(TokenType || (TokenType = {}));\nexport class Lexer {\n constructor(source) {\n this.source = source;\n this.pos = 0;\n this.line = 1;\n this.column = 1;\n }\n peek() {\n return this.source[this.pos] || '';\n }\n advance() {\n const char = this.peek();\n this.pos++;\n if (char === '\\n') {\n this.line++;\n this.column = 1;\n }\n else {\n this.column++;\n }\n return char;\n }\n tokenize() {\n const tokens = [];\n while (this.pos < this.source.length) {\n const char = this.peek();\n if (/\\s/.test(char) && char !== '\\n') {\n this.advance();\n }\n else if (char === ';') {\n // Skip comments\n while (this.peek() !== '\\n' && this.pos < this.source.length) {\n this.advance();\n }\n }\n else if (char === '\\n') {\n tokens.push({ type: TokenType.NEWLINE, value: '\\n', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ',') {\n tokens.push({ type: TokenType.COMMA, value: ',', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ':') {\n tokens.push({ type: TokenType.COLON, value: ':', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === '(') {\n tokens.push({ type: TokenType.LPAREN, value: '(', line: this.line, column: this.column });\n this.advance();\n }\n else if (char === ')') {\n tokens.push({ type: TokenType.RPAREN, value: ')', line: this.line, column: this.column });\n this.advance();\n }\n else if (/[a-zA-Z_]/.test(char)) {\n tokens.push(this.readIdentifier());\n }\n else if (/[0-9.]/.test(char) || char === '$' || char === '%') {\n tokens.push(this.readNumber());\n }\n else if (/[-+*/|&<>^!]/.test(char)) {\n tokens.push({ type: TokenType.OPERATOR, value: this.advance(), line: this.line, column: this.column });\n }\n else {\n // Unknown character\n this.advance();\n }\n }\n tokens.push({ type: TokenType.EOF, value: '', line: this.line, column: this.column });\n return tokens;\n }\n readIdentifier() {\n let value = '';\n const startLine = this.line;\n const startCol = this.column;\n while (/[a-zA-Z0-9_#^.]/.test(this.peek())) {\n value += this.advance();\n }\n const upper = value.toUpperCase();\n if (['EQU', 'MEM'].includes(upper)) {\n return { type: TokenType.DIRECTIVE, value: upper, line: startLine, column: startCol };\n }\n // Mnemonics are checked during parsing or here. Let's keep them as identifiers for now \n // and resolve them in the parser.\n return { type: TokenType.IDENTIFIER, value: upper, line: startLine, column: startCol };\n }\n readNumber() {\n let value = '';\n const startLine = this.line;\n const startCol = this.column;\n if (this.peek() === '$') {\n value += this.advance();\n while (/[0-9a-fA-F]/.test(this.peek()))\n value += this.advance();\n }\n else if (this.peek() === '%') {\n value += this.advance();\n while (/[01_]/.test(this.peek()))\n value += this.advance();\n }\n else if (this.peek() === '0' && (this.source[this.pos + 1] || '').toLowerCase() === 'x') {\n value += this.advance(); // 0\n value += this.advance(); // x\n while (/[0-9a-fA-F]/.test(this.peek()))\n value += this.advance();\n }\n else {\n while (/[0-9\\.]/.test(this.peek()))\n value += this.advance();\n }\n return { type: TokenType.NUMBER, value, line: startLine, column: startCol };\n }\n}\nexport class Parser {\n constructor(tokens) {\n this.pos = 0;\n this.tokens = tokens.filter((t, i) => t.type !== TokenType.NEWLINE || this.isNextSignificant(tokens, i));\n }\n isNextSignificant(tokens, index) {\n // Only keep newlines if they are followed by something that isn't a newline or EOF\n for (let i = index + 1; i < tokens.length; i++) {\n if (tokens[i].type !== TokenType.NEWLINE) {\n return tokens[i].type !== TokenType.EOF;\n }\n }\n return false;\n }\n peek() {\n return this.tokens[this.pos] || { type: TokenType.EOF, value: '', line: -1, column: -1 };\n }\n advance() {\n return this.tokens[this.pos++];\n }\n match(type) {\n if (this.peek().type === type)\n return this.advance();\n return null;\n }\n parse() {\n const nodes = [];\n while (this.peek().type !== TokenType.EOF) {\n const node = this.parseStatement();\n if (node)\n nodes.push(node);\n // Consume optional newline\n while (this.match(TokenType.NEWLINE))\n ;\n }\n return nodes;\n }\n parseStatement() {\n const token = this.peek();\n if (token.type === TokenType.IDENTIFIER) {\n const next = this.tokens[this.pos + 1];\n // Label: IDENTIFIER:\n if (next && next.type === TokenType.COLON) {\n const label = this.advance();\n this.advance(); // consume :\n return { type: 'Label', name: label.value, line: label.line };\n }\n // Directive: IDENTIFIER EQU EXPR or EQU IDENTIFIER EXPR\n if (next && next.type === TokenType.DIRECTIVE) {\n const id = this.advance();\n const dir = this.advance();\n const expr = this.parseExpression();\n return { type: 'Directive', name: dir.value, identifier: id.value, expression: expr, line: dir.line };\n }\n }\n if (token.type === TokenType.DIRECTIVE) {\n const dir = this.advance();\n const id = this.match(TokenType.IDENTIFIER);\n if (!id)\n throw new ParserError(`Expected identifier after ${dir.value}`, dir.line, dir.column);\n const expr = this.parseExpression();\n return { type: 'Directive', name: dir.value, identifier: id.value, expression: expr, line: dir.line };\n }\n if (token.type === TokenType.IDENTIFIER) {\n const mnemonic = this.advance();\n const operands = [];\n if (this.peek().type !== TokenType.NEWLINE && this.peek().type !== TokenType.EOF) {\n operands.push(this.parseExpression());\n while (this.match(TokenType.COMMA)) {\n operands.push(this.parseExpression());\n }\n }\n return { type: 'Instruction', mnemonic: mnemonic.value, operands, line: mnemonic.line };\n }\n this.advance(); // Skip unknown\n return null;\n }\n parseExpression() {\n return this.parseBitwise();\n }\n parseBitwise() {\n let left = this.parseShift();\n while (this.peek().type === TokenType.OPERATOR && (['|', '&', '^'].includes(this.peek().value))) {\n const operator = this.advance().value;\n const right = this.parseShift();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseShift() {\n let left = this.parseAdditive();\n while (this.peek().type === TokenType.OPERATOR && (['<', '>'].includes(this.peek().value))) {\n const operator = this.advance().value;\n const right = this.parseAdditive();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseAdditive() {\n let left = this.parseMultiplicative();\n while (this.peek().type === TokenType.OPERATOR && (this.peek().value === '+' || this.peek().value === '-')) {\n const operator = this.advance().value;\n const right = this.parseMultiplicative();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parseMultiplicative() {\n let left = this.parsePrimary();\n while (this.peek().type === TokenType.OPERATOR && (this.peek().value === '*' || this.peek().value === '/')) {\n const operator = this.advance().value;\n const right = this.parsePrimary();\n left = { type: 'Binary', left, operator, right };\n }\n return left;\n }\n parsePrimary() {\n const token = this.peek();\n if (token.type === TokenType.NUMBER) {\n return { type: 'Number', value: this.parseNumberValue(this.advance().value) };\n }\n if (token.type === TokenType.IDENTIFIER) {\n return { type: 'Identifier', name: this.advance().value };\n }\n if (token.type === TokenType.LPAREN) {\n this.advance();\n const expr = this.parseExpression();\n if (!this.match(TokenType.RPAREN))\n throw new ParserError(`Expected )`, token.line, token.column);\n return expr;\n }\n if (token.type === TokenType.OPERATOR && (token.value === '-' || token.value === '+' || token.value === '!')) {\n const operator = this.advance().value;\n return { type: 'Unary', operator, expression: this.parsePrimary() };\n }\n throw new ParserError(`Unexpected token ${token.value}`, token.line, token.column);\n }\n parseNumberValue(val) {\n const upper = val.toUpperCase();\n if (upper.startsWith('$'))\n return parseInt(val.slice(1), 16);\n if (upper.startsWith('0X'))\n return parseInt(val, 16);\n if (upper.startsWith('%'))\n return parseInt(val.slice(1).replace(/_/g, ''), 2);\n return parseFloat(val);\n }\n}\n//# sourceMappingURL=FV1Parser.js.map","export const INSTRUCTION_SET = {\n // Accumulator\n 'SOF': {\n opcode: 0b01101, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S_10' },\n { name: 'op', bits: 5, offset: 0, value: 0b01101 }\n ]\n },\n 'AND': {\n opcode: 0b01110, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b01110 }\n ]\n },\n 'OR': {\n opcode: 0b01111, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b01111 }\n ]\n },\n 'XOR': {\n opcode: 0b10000, fields: [\n { name: 'mask', bits: 24, offset: 8, type: 'U' },\n { name: 'op', bits: 8, offset: 0, value: 0b10000 }\n ]\n },\n 'LOG': {\n opcode: 0b01011, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S4_6' },\n { name: 'op', bits: 5, offset: 0, value: 0b01011 }\n ]\n },\n 'EXP': {\n opcode: 0b01100, fields: [\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'd', bits: 11, offset: 5, type: 'S_10' },\n { name: 'op', bits: 5, offset: 0, value: 0b01100 }\n ]\n },\n 'SKP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, type: 'LFO' }, // Special handling for flag bits\n { name: 'n', bits: 6, offset: 21, type: 'S' },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n 'JMP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, value: 0 },\n { name: 'n', bits: 6, offset: 21, type: 'S' },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n 'NOP': {\n opcode: 0b10001, fields: [\n { name: 'flags', bits: 5, offset: 27, value: 0 },\n { name: 'n', bits: 6, offset: 21, value: 0 },\n { name: 'op', bits: 5, offset: 0, value: 0b10001 }\n ]\n },\n // Register\n 'RDAX': {\n opcode: 0b00100, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00100 }\n ]\n },\n 'WRAX': {\n opcode: 0b00110, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00110 }\n ]\n },\n 'MAXX': {\n opcode: 0b01001, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b01001 }\n ]\n },\n 'MULX': {\n opcode: 0b01010, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'op', bits: 5, offset: 0, value: 0b01010 }\n ]\n },\n 'RDFX': {\n opcode: 0b00101, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00101 }\n ]\n },\n 'WRLX': {\n opcode: 0b01000, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b01000 }\n ]\n },\n 'WRHX': {\n opcode: 0b00111, fields: [\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'coeff', bits: 16, offset: 16, type: 'S1_14' },\n { name: 'op', bits: 5, offset: 0, value: 0b00111 }\n ]\n },\n 'LDAX': {\n opcode: 0b00101, fields: [\n { name: 'coeff', bits: 16, offset: 16, value: 0 },\n { name: 'addr', bits: 6, offset: 5, type: 'REG' },\n { name: 'op', bits: 5, offset: 0, value: 0b00101 }\n ]\n },\n // Delay RAM\n 'RDA': {\n opcode: 0b00000, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00000 }\n ]\n },\n 'RMPA': {\n opcode: 0b00001, fields: [\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00001 }\n ]\n },\n 'WRA': {\n opcode: 0b00010, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00010 }\n ]\n },\n 'WRAP': {\n opcode: 0b00011, fields: [\n { name: 'addr', bits: 16, offset: 5, type: 'ADDR' },\n { name: 'coeff', bits: 11, offset: 21, type: 'S1_9' },\n { name: 'op', bits: 5, offset: 0, value: 0b00011 }\n ]\n },\n // LFO/CHO\n 'WLDS': {\n opcode: 0b10010, fields: [\n { name: 'sinLfo', bits: 1, offset: 29, type: 'U' }, // N\n { name: 'freq', bits: 9, offset: 20, type: 'U' }, // F\n { name: 'ampl', bits: 15, offset: 5, type: 'U' }, // A\n { name: 'op', bits: 5, offset: 0, value: 0b10010 }\n ]\n },\n 'WLDR': {\n opcode: 0b10010, fields: [\n { name: 'type', bits: 1, offset: 30, value: 1 }, // Always 1 for WLDR\n { name: 'rmpLfo', bits: 1, offset: 29, type: 'U' }, // N\n { name: 'freq', bits: 16, offset: 13, type: 'U' }, // F (signed 16-bit)\n { name: 'ampl', bits: 2, offset: 5, type: 'U' }, // A (backward encoding handled in assembler)\n { name: 'op', bits: 5, offset: 0, value: 0b10010 }\n ]\n },\n 'JAM': {\n opcode: 0b10011, fields: [\n { name: 'rmpLfo', bits: 1, offset: 6, type: 'U' },\n { name: 'type', bits: 1, offset: 7, value: 1 },\n { name: 'op', bits: 5, offset: 0, value: 0b10011 }\n ]\n },\n 'CHO': {\n opcode: 0b10100, fields: [\n { name: 'mode', bits: 2, offset: 30, type: 'U' },\n { name: 'flags', bits: 6, offset: 24, type: 'U' },\n { name: 'n', bits: 3, offset: 21, type: 'U' },\n { name: 'param', bits: 16, offset: 5, type: 'ADDR' }, // Can be addr or coeff\n { name: 'op', bits: 5, offset: 0, value: 0b10100 }\n ]\n },\n // Pseudo-ops\n 'CLR': { opcode: 0b01110, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b01110 }] },\n 'NOT': { opcode: 0b10000, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b10000 }] },\n 'ABSA': { opcode: 0b01001, fields: [{ name: 'val', bits: 32, offset: 0, value: 0b01001 }] },\n};\nexport class Encoder {\n static encode(format, value) {\n switch (format) {\n case 'S1_14': return this.toFixedPoint(value, 1, 14, 2.0);\n case 'S_15': return this.toFixedPoint(value, 0, 15, 1.0);\n case 'S1_9': return this.toFixedPoint(value, 1, 9, 2.0);\n case 'S_10': return this.toFixedPoint(value, 0, 10, 1.0);\n case 'S4_6': return this.toFixedPoint(value, 4, 6, 16.0);\n }\n return value;\n }\n static toFixedPoint(value, intBits, fracBits, maxValue) {\n const lsb = maxValue / (1 << fracBits);\n const min = -maxValue;\n const max = maxValue - lsb;\n let num = Math.min(Math.max(value, min), max);\n let encoded = Math.trunc(num * (1 << fracBits));\n const totalBits = 1 + intBits + fracBits;\n const mask = (1 << totalBits) - 1;\n return (encoded < 0) ? (encoded + (1 << totalBits)) & mask : encoded & mask;\n }\n static assembleInstruction(mnemonic, operands, schema) {\n let result = 0;\n let operandIdx = 0;\n for (const field of schema.fields) {\n let val = 0;\n if (field.value !== undefined) {\n val = field.value;\n }\n else {\n val = operands[operandIdx++];\n if (field.type)\n val = this.encode(field.type, val);\n }\n const mask = field.bits === 32 ? 0xFFFFFFFF : (1 << field.bits) - 1;\n result |= (val & mask) << field.offset;\n }\n return result >>> 0;\n }\n}\n//# sourceMappingURL=FV1Encoder.js.map","import { Lexer, Parser, ParserError } from './FV1Parser.js';\nimport { INSTRUCTION_SET, Encoder } from './FV1Encoder.js';\nexport class FV1Assembler {\n constructor(options = {}) {\n this.problems = [];\n this.symbols = new Map();\n this.memories = [];\n this.labels = new Map();\n this.addressToLineMap = new Map();\n this.usedRegisters = new Set();\n this.usedLFOs = new Set();\n this.configuredLFOs = new Set();\n this.userSymbols = new Set();\n this.symbolLines = new Map();\n this.PREDEFINED_SYMBOLS = {\n 'SIN0_RATE': 0x00, 'SIN0_RANGE': 0x01, 'SIN1_RATE': 0x02, 'SIN1_RANGE': 0x03,\n 'RMP0_RATE': 0x04, 'RMP0_RANGE': 0x05, 'RMP1_RATE': 0x06, 'RMP1_RANGE': 0x07,\n 'POT0': 0x10, 'POT1': 0x11, 'POT2': 0x12, 'ADCL': 0x14, 'ADCR': 0x15,\n 'DACL': 0x16, 'DACR': 0x17, 'ADDR_PTR': 0x18,\n 'SIN0': 0x00, 'SIN1': 0x01, 'RMP0': 0x02, 'RMP1': 0x03,\n 'COS0': 0x08, 'COS1': 0x09,\n 'RDA': 0x00, 'SOF': 0x02, 'RDAL': 0x03,\n 'SIN': 0x00, 'COS': 0x01, 'REG': 0x02, 'COMPC': 0x04,\n 'COMPA': 0x08, 'RPTR2': 0x10, 'NA': 0x20,\n 'RUN': 0x10, 'ZRC': 0x08, 'ZRO': 0x04,\n 'GEZ': 0x02, 'NEG': 0x01\n };\n this.reservedSymbols = new Set();\n this.options = {\n fv1AsmMemBug: options.fv1AsmMemBug ?? true,\n clampReals: options.clampReals ?? true,\n regCount: options.regCount ?? 32,\n progSize: options.progSize ?? 128,\n delaySize: options.delaySize ?? 32768\n };\n this.reset();\n }\n reset() {\n this.problems = [];\n this.symbols.clear();\n this.memories = [];\n this.labels.clear();\n this.addressToLineMap.clear();\n this.usedRegisters.clear();\n this.usedLFOs.clear();\n this.configuredLFOs.clear();\n this.userSymbols.clear();\n this.symbolLines.clear(); // Added this line\n this.initSymbols(); // Added this line\n }\n initSymbols() {\n // Load predefined symbols\n for (const [key, val] of Object.entries(this.PREDEFINED_SYMBOLS)) {\n this.symbols.set(key, val);\n this.reservedSymbols.add(key);\n }\n // Load REG0-31\n for (let i = 0; i < this.options.regCount; i++) {\n this.symbols.set(`REG${i}`, 0x20 + i);\n this.reservedSymbols.add(`REG${i}`);\n }\n }\n assemble(source) {\n this.reset();\n try {\n const lexer = new Lexer(source);\n const tokens = lexer.tokenize();\n const parser = new Parser(tokens);\n const ast = parser.parse();\n this.pass1_ResolveDirectives(ast);\n this.pass2_ResolveLabels(ast);\n const machineCode = this.pass3_GenerateCode(ast);\n return {\n machineCode,\n problems: this.problems,\n labels: this.labels,\n symbols: Array.from(this.symbols.entries())\n .filter(([name]) => this.userSymbols.has(name))\n .map(([name, value]) => ({ name, value: value.toString(), line: this.symbolLines.get(name) })),\n memories: this.memories,\n addressToLineMap: this.addressToLineMap,\n usedRegistersCount: this.usedRegisters.size,\n usedLFOs: Array.from(this.usedLFOs)\n };\n }\n catch (e) {\n const line = (e instanceof ParserError) ? e.line : 1;\n this.problems.push({ message: `Parser error: ${e instanceof Error ? e.message : String(e)}`, isfatal: true, line });\n return {\n machineCode: [],\n problems: this.problems,\n labels: new Map(),\n symbols: [],\n memories: [],\n addressToLineMap: new Map(),\n usedRegistersCount: 0,\n usedLFOs: []\n };\n }\n }\n pass1_ResolveDirectives(ast) {\n let nextDelayAddr = 0;\n for (const node of ast) {\n if (node.type === 'Directive') {\n if (node.name === 'EQU') {\n if (this.reservedSymbols.has(node.identifier)) {\n this.problems.push({ message: `Cannot redefine reserved symbol '${node.identifier}'`, isfatal: true, line: node.line });\n }\n else if (this.userSymbols.has(node.identifier)) {\n this.problems.push({ message: `Symbol '${node.identifier}' is already defined on line ${this.symbolLines.get(node.identifier)}`, isfatal: true, line: node.line });\n }\n else {\n const value = this.evaluateExpression(node.expression, node.line);\n this.symbols.set(node.identifier, value);\n this.userSymbols.add(node.identifier);\n this.symbolLines.set(node.identifier, node.line);\n }\n }\n else if (node.name === 'MEM') {\n if (this.reservedSymbols.has(node.identifier)) {\n this.problems.push({ message: `Cannot redefine reserved symbol '${node.identifier}'`, isfatal: true, line: node.line });\n continue;\n }\n const size = this.evaluateExpression(node.expression, node.line);\n const start = nextDelayAddr;\n const middle = start + (size % 2 ? (size - 1) / 2 - 1 : size / 2);\n const end = start + size - 1;\n const buggyEnd = end + (this.options.fv1AsmMemBug ? 1 : 0);\n const mem = { name: node.identifier, size, start, middle, end, line: node.line, original: '' };\n this.memories.push(mem);\n // Register special suffixes\n this.symbols.set(node.identifier, start);\n this.symbols.set(node.identifier + '^', middle);\n this.symbols.set(node.identifier + '#', buggyEnd);\n nextDelayAddr = buggyEnd + 1;\n }\n }\n }\n }\n pass2_ResolveLabels(ast) {\n let pc = 0;\n for (const node of ast) {\n if (node.type === 'Label') {\n this.labels.set(node.name, { line: node.line, instructionLine: pc });\n }\n else if (node.type === 'Instruction') {\n pc++;\n }\n }\n }\n pass3_GenerateCode(ast) {\n const code = [];\n let pc = 0;\n for (const node of ast) {\n if (node.type === 'Instruction') {\n const schema = INSTRUCTION_SET[node.mnemonic];\n if (!schema) {\n this.problems.push({ message: `Unknown instruction ${node.mnemonic}`, isfatal: true, line: node.line });\n code.push(0);\n continue;\n }\n let operands = node.operands.map(op => {\n // Special case for labels in JMP/SKP\n if (op.type === 'Identifier' && this.labels.has(op.name)) {\n return this.labels.get(op.name).instructionLine - pc - 1;\n }\n return this.evaluateExpression(op, node.line);\n });\n // --- Specialized Encoding Logic ---\n // LFO Tracking for configurations\n if (node.mnemonic === 'WLDS' || node.mnemonic === 'WLDR') {\n const lfoReg = operands[0];\n const lfoName = this.getLFOName(lfoReg);\n if (lfoName) {\n if (node.mnemonic === 'WLDS') {\n if (this.configuredLFOs.has(lfoName)) {\n this.problems.push({ message: `LFO ${lfoName} is configured more than once`, isfatal: true, line: node.line });\n }\n this.configuredLFOs.add(lfoName);\n }\n this.usedLFOs.add(lfoName);\n }\n }\n if (node.mnemonic === 'CHO') {\n const mode = operands[0];\n const n = operands[1];\n const rdaMode = this.symbols.get('RDA');\n const sofMode = this.symbols.get('SOF');\n const rdalMode = this.symbols.get('RDAL');\n if (mode === rdalMode) {\n // CHO RDAL, N -> [mode, flags=0x02(fixed bit 25), n, param=0]\n operands = [mode, 0x02, n, 0];\n }\n else if (mode === rdaMode || mode === sofMode) {\n const flags = operands[2];\n let param = operands[3];\n if (mode === sofMode) {\n param = Encoder.encode('S1_14', param);\n }\n operands = [mode, flags, n, param];\n }\n }\n else if (node.mnemonic === 'WLDR') {\n // Match previous backwards-encoded amplitude\n let ampl = operands[2];\n switch (ampl) {\n case 512:\n ampl = 3;\n break;\n case 1024:\n ampl = 2;\n break;\n case 2048:\n ampl = 1;\n break;\n case 4096:\n ampl = 0;\n break;\n default:\n this.problems.push({ message: `Invalid amplitude ${ampl} for WLDR`, isfatal: true, line: node.line });\n }\n // Handle RMP LFO mapping\n let rmpLfo = operands[0];\n if ([0, 2].includes(rmpLfo))\n rmpLfo = 0;\n else if ([1, 3].includes(rmpLfo))\n rmpLfo = 1;\n operands = [rmpLfo, operands[1], ampl];\n }\n else if (node.mnemonic === 'JAM') {\n let rmpLfo = operands[0];\n if ([0, 2].includes(rmpLfo))\n rmpLfo = 0;\n else if ([1, 3].includes(rmpLfo))\n rmpLfo = 1;\n operands = [rmpLfo];\n }\n // Track register usage\n schema.fields.forEach((field, i) => {\n if (field.type === 'REG' && operands[i] !== undefined) {\n this.trackRegister(operands[i], node.line);\n }\n });\n // Additional LFO tracking for register writes to RATE/RANGE\n if (node.mnemonic === 'WRAX' || node.mnemonic === 'RDAX') {\n const regNum = operands[0];\n const lfoName = this.getLFONameFromRegister(regNum);\n if (lfoName) {\n this.usedLFOs.add(lfoName);\n }\n }\n code.push(Encoder.assembleInstruction(node.mnemonic, operands, schema));\n this.addressToLineMap.set(pc, node.line);\n pc++;\n }\n }\n // Pad to progSize\n while (code.length < this.options.progSize)\n code.push(0x00000011); // NOP\n return code;\n }\n trackRegister(addr, line) {\n if (addr >= 0x20 && addr <= 0x3F) {\n const regNum = addr - 0x20;\n if (regNum >= this.options.regCount) {\n this.problems.push({ message: `Register REG${regNum} exceeds limit ${this.options.regCount}`, isfatal: true, line });\n }\n this.usedRegisters.add(regNum);\n }\n }\n getLFOName(lfoId) {\n switch (lfoId) {\n case 0: return 'SIN0';\n case 1: return 'SIN1';\n case 2: return 'RMP0';\n case 3: return 'RMP1';\n default: return null;\n }\n }\n getLFONameFromRegister(addr) {\n // 0x00=SIN0_RATE, 0x01=SIN0_RANGE, 0x02=SIN1_RATE, 0x03=SIN1_RANGE\n // 0x04=RMP0_RATE, 0x05=RMP0_RANGE, 0x06=RMP1_RATE, 0x07=RMP1_RANGE\n switch (addr) {\n case 0x00:\n case 0x01: return 'SIN0';\n case 0x02:\n case 0x03: return 'SIN1';\n case 0x04:\n case 0x05: return 'RMP0';\n case 0x06:\n case 0x07: return 'RMP1';\n default: return null;\n }\n }\n evaluateExpression(expr, line) {\n switch (expr.type) {\n case 'Number': return expr.value;\n case 'Identifier':\n if (this.symbols.has(expr.name))\n return this.symbols.get(expr.name);\n this.problems.push({ message: `Undefined symbol ${expr.name}`, isfatal: true, line });\n return 0;\n case 'Binary':\n const left = this.evaluateExpression(expr.left, line);\n const right = this.evaluateExpression(expr.right, line);\n switch (expr.operator) {\n case '+': return left + right;\n case '-': return left - right;\n case '*': return left * right;\n case '/': return left / right;\n case '|': return left | right;\n case '&': return left & right;\n case '^': return left ^ right;\n case '<': return (left << right) >>> 0;\n case '>': return (left >>> right);\n default: return 0;\n }\n case 'Unary':\n const val = this.evaluateExpression(expr.expression, line);\n if (expr.operator === '-')\n return -val;\n if (expr.operator === '!')\n return (~Math.floor(val)) >>> 0;\n return val;\n }\n }\n static formatMachineCode(machineCode) {\n return machineCode.map((word, index) => `${index.toString().padStart(4, '0')}\\t${word.toString(16).toUpperCase().padStart(8, '0')}`).join('\\n');\n }\n static toUint8Array(machineCode) {\n const buffer = new ArrayBuffer(machineCode.length * 4);\n const view = new DataView(buffer);\n machineCode.forEach((val, i) => view.setUint32(i * 4, val, false));\n return new Uint8Array(buffer);\n }\n static getMiddleAddr(start, size) {\n return start + (size % 2 ? (size - 1) / 2 - 1 : size / 2);\n }\n static getEndAddr(start, size, fv1AsmMemBug) {\n return start + size - 1 + (fv1AsmMemBug ? 1 : 0);\n }\n}\n//# sourceMappingURL=FV1Assembler.js.map","/**\n * FV-1 DSP Simulator\n *\n * Simulates the Spin Semiconductor FV-1 DSP chip.\n * This class is designed to be platform-agnostic (Node.js or Browser/AudioWorklet).\n */\nimport { FV1Assembler } from '../assembler/FV1Assembler.js';\nexport class FV1Simulator {\n // Register aliases (Getters/Setters)\n // 0-7: Parameters\n // These are now handled by updateStateRegisters for debugger view\n // 8-13: Internal State accumulators (aliased as registers for the debugger)\n // These are now handled by updateStateRegisters for debugger view\n constructor() {\n // Constants\n // Capabilities (Configurable)\n this.delaySize = 32768;\n this.delayMask = 32767; // For efficient circular buffer\n this.regCount = 32;\n this.progSize = 128;\n // --- Float-based LFO state (from Expert Sleepers C port) ---\n this.sin0 = 0;\n this.cos0 = 0;\n this.sin1 = 0;\n this.cos1 = 0;\n this.rmp0 = 0;\n this.rmp1 = 0;\n this.sin0_rate = 0;\n this.sin0_range = 0;\n this.sin1_rate = 0;\n this.sin1_range = 0;\n this.rmp0_rate = 0;\n this.rmp0_range = 0;\n this.rmp1_rate = 0;\n this.rmp1_range = 0;\n this.acc = 0;\n this.pacc = 0;\n this.lr = 0; // Last Read register\n this.lfo = 0; // Internal LFO fregister (for CHO)\n this.delayPointer = 0; // Circular buffer pointer\n this.firstRun = true;\n this.pc = 0; // Program Counter\n this.breakpoints = new Set();\n // Symbol metadata (optional, for debugging)\n this.symbols = [];\n this.memories = [];\n this.fv1AsmMemBug = false;\n // --- Trace Logging ---\n this.traceEnabled = false;\n this.traceWriter = null; // Streaming callback\n this.cycleCount = 0;\n this.traceCycle = 0;\n this.traceMaxCycles = 0; // 0 = unlimited\n this.traceRowCount = 0;\n this.traceDelayAddr = -1; // computed physical address in delay RAM\n this.traceDelayOffset = -1; // raw offset from instruction (identifies MEM block)\n this.traceDelayOp = ''; // 'R' for read, 'W' for write\n this.traceDelayValue = 0; // value read/written\n this.traceInstructionPC = -1; // PC of currently executing instruction\n this.currentReadOffsets = new Set(); // Tracks read offsets in current sample cycle\n this.traceOnComplete = null;\n this.delayRam = new Float32Array(this.delaySize);\n this.registers = new Float32Array(32 + this.regCount);\n this.program = new Uint32Array(this.progSize);\n }\n /**\n * Configures simulator hardware limits.\n */\n setCapabilities(delaySize, regCount, progSize) {\n this.delaySize = delaySize;\n this.delayMask = delaySize - 1; // Assuming power of 2 for now, but modulo is fallback\n this.regCount = regCount; // Number of user registers\n this.progSize = progSize;\n // Reallocate if needed\n this.delayRam = new Float32Array(this.delaySize);\n this.registers = new Float32Array(32 + this.regCount); // 32 system + N user registers\n this.program = new Uint32Array(this.progSize);\n this.reset();\n }\n getDelayPointer() {\n return this.delayPointer;\n }\n getDelaySize() {\n return this.delaySize;\n }\n /**\n * Loads the machine code into the simulator.\n * @param code Array of 32-bit integers representing the assembled program.\n */\n loadProgram(code) {\n if (code.length > this.progSize) {\n console.warn(`Program size (${code.length}) exceeds max size (${this.progSize}). Truncating.`);\n }\n this.program.fill(0);\n this.program.set(code.slice(0, this.progSize));\n this.reset();\n }\n /**\n * Resets the simulator state (clears memory, registers, accumulator).\n */\n reset() {\n this.delayRam.fill(0);\n this.registers.fill(0);\n this.acc = 0;\n this.pacc = 0;\n this.lr = 0;\n this.lfo = 0;\n this.pc = 0;\n this.delayPointer = 0;\n this.firstRun = true;\n this.sin0 = 0;\n this.sin1 = 0;\n // Peak amplitude from Java SinLFO.java initialized to -0x7fff00 mapped to float (-1.0)\n // BUT wait, in C the initialization is not explicit, we can just use 1.0 or -1.0\n // SpinCAD sets cos to -0x7fff00l which is approx -1.0\n this.cos0 = -1.0;\n this.cos1 = -1.0;\n this.rmp0 = 0;\n this.rmp1 = 0;\n this.sin0_rate = 0;\n this.sin0_range = 0;\n this.sin1_rate = 0;\n this.sin1_range = 0;\n this.rmp0_rate = 0;\n this.rmp0_range = 0;\n this.rmp1_rate = 0;\n this.rmp1_range = 0;\n // Default POT values to 0.5\n this.registers[16] = 0.5;\n this.registers[17] = 0.5;\n this.registers[18] = 0.5;\n }\n /**\n * Set breakpoints at specific instruction addresses.\n * @param addresses Set of addresses to break at.\n */\n setBreakpoints(addresses) {\n this.breakpoints = addresses;\n }\n /**\n * Set symbol and memory metadata for expression evaluation.\n */\n setSymbols(symbols, memories, fv1AsmMemBug = false) {\n this.symbols = symbols;\n this.memories = memories;\n this.fv1AsmMemBug = fv1AsmMemBug;\n }\n /**\n * Process a block of audio samples.\n * Useful for real-time audio processing in AudioWorklets.\n */\n processBlock(inputL, inputR, outputL, outputR, pot0, pot1, pot2) {\n const len = inputL.length;\n for (let i = 0; i < len; i++) {\n const [outL, outR] = this.step(inputL[i], inputR[i], pot0, pot1, pot2);\n outputL[i] = outL;\n outputR[i] = outR;\n }\n }\n /**\n * Process a single sample frame.\n * Executes instructions until the end of the program or a breakpoint is hit.\n * @param skipCurrentBreakpoint If true, will not break on the instruction at the current PC.\n * @returns [outL, outR, breakpointHit]\n */\n step(inL, inR, pot0, pot1, pot2, skipCurrentBreakpoint = false) {\n // Only begin a new frame if we are at PC 0 (either start or after wrap around)\n if (this.pc === 0) {\n this.beginFrame(inL, inR, pot0, pot1, pot2);\n }\n let firstInstruction = true;\n while (this.pc < this.progSize) {\n if (this.breakpoints.has(this.pc)) {\n if (!firstInstruction || !skipCurrentBreakpoint) {\n return [...this.getOutputs(), true];\n }\n }\n this.stepInstruction();\n firstInstruction = false;\n }\n return [...this.endFrame(), false];\n }\n getOutputs() {\n return [this.registers[22], this.registers[23]];\n }\n beginFrame(inL = 0, inR = 0, pot0 = 0, pot1 = 0, pot2 = 0) {\n this.cycleCount++;\n this.currentReadOffsets.clear();\n // Saturate inputs (ADC is -1.0 to 0.999..., POT is 0 to 0.999...)\n // POT has 10-bit resolution (1024 levels)\n const sat = (v) => Math.max(-1.0, Math.min(FV1Simulator.MAX_ACC, v));\n const satPot = (v) => {\n const quantized = Math.floor(Math.max(0, Math.min(0.9999999, v)) * 1024) / 1024;\n return quantized;\n };\n // Execute Program Setup\n this.acc = 0; // Accumulator is cleared at start of run\n this.lr = 0; // LR is transient\n this.pacc = 0;\n this.pc = 0;\n // Map inputs to registers (Standard FV-1 mapping)\n this.registers[20] = sat(inL);\n this.registers[21] = sat(inR);\n this.registers[16] = satPot(pot0);\n this.registers[17] = satPot(pot1);\n this.registers[18] = satPot(pot2);\n this.updateStateRegisters();\n }\n endFrame() {\n this.pc = 0;\n this.firstRun = false;\n this.updateLFOs();\n this.updateStateRegisters();\n this.advanceTraceCycle();\n // Advance Delay Pointer (Circular Buffer)\n this.delayPointer = (this.delayPointer - 1 + this.delaySize) % this.delaySize;\n // Outputs (DACL = REG22, DACR = REG23)\n return [this.registers[22], this.registers[23]];\n }\n /**\n * Executes a single instruction at the current PC.\n * @returns The next PC address.\n */\n stepInstruction() {\n if (this.pc >= this.progSize)\n return this.pc;\n const inst = this.program[this.pc];\n const opcode = inst & 0x1F;\n const preOpAcc = this.acc;\n // Reset per-instruction trace state\n this.traceDelayAddr = -1;\n this.traceDelayOffset = -1;\n this.traceDelayOp = '';\n this.traceDelayValue = 0;\n this.traceInstructionPC = this.pc;\n const skip = this.executeInstruction(inst);\n // Trace log AFTER instruction executes so ACC reflects the result\n if (this.traceEnabled) {\n this.logTrace(this.traceInstructionPC, opcode, inst, preOpAcc);\n }\n if (opcode !== 0x11) { // Not SKP\n this.pacc = preOpAcc;\n }\n this.pc += 1 + skip;\n return this.pc;\n }\n executeInstruction(inst) {\n const opcode = inst & 0x1F; // Bottom 5 bits for opcode\n let skip = 0;\n switch (opcode) {\n case 0x00: // RDA (Read Delay Accumulate)\n this.opRDA(inst);\n break;\n case 0x01: // RMPA (Read Memory Pointer Accumulate)\n this.opRMPA(inst);\n break;\n case 0x02: // WRA (Write Delay Accumulate)\n this.opWRA(inst);\n break;\n case 0x03: // WRAP (Write Delay Accumulate & Pointer)\n this.opWRAP(inst);\n break;\n case 0x04: // RDAX (Read Register Accumulate)\n this.opRDAX(inst);\n break;\n case 0x05: // RDFX (Read Register Filter)\n this.opRDFX(inst);\n break;\n case 0x06: // WRAX (Write Register Accumulate)\n this.opWRAX(inst);\n break;\n case 0x07: // WRHX (Write Register High)\n this.opWRHX(inst);\n break;\n case 0x08: // WRLX (Write Register Low)\n this.opWRLX(inst);\n break;\n case 0x09: // MAXX\n this.opMAXX(inst);\n break;\n case 0x0A: // MULX\n this.opMULX(inst);\n break;\n case 0x0B: // LOG\n this.opLOG(inst);\n break;\n case 0x0C: // EXP\n this.opEXP(inst);\n break;\n case 0x0D: // SOF\n this.opSOF(inst);\n break;\n case 0x0E: // AND\n this.opAND(inst);\n break;\n case 0x0F: // OR\n this.opOR(inst);\n break;\n case 0x10: // XOR\n this.opXOR(inst);\n break;\n case 0x11: // SKP\n skip = this.opSKP(inst);\n break;\n case 0x12: // WLDS / WLDR\n // Check bit 30 to distinguish WLDS (0) and WLDR (1)\n if ((inst >>> 30) & 1) {\n this.opWLDR(inst);\n }\n else {\n this.opWLDS(inst);\n }\n break;\n case 0x13: // JAM\n this.opJAM(inst);\n break;\n case 0x14: // CHO\n this.opCHO(inst);\n break;\n default:\n // console.warn(`Unknown opcode: ${opcode.toString(16)}`);\n break;\n }\n return skip;\n }\n // --- Opcode Implementations ---\n opRDA(inst) {\n // ... (existing comments)\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n // Address is relative to current delay pointer in circular buffer\n const readAddr = (this.delayPointer + addr) & this.delayMask;\n const val = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'R';\n this.traceDelayValue = val;\n this.currentReadOffsets.add(addr);\n this.lr = val;\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRA(inst) {\n // WRA addr, coeff\n // Delay[addr] = ACC; ACC = ACC * coeff\n // Encoding: CCCCCCCCCCCAAAAAAAAAAAAAAAA00010\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n const writeAddr = (this.delayPointer + addr) & this.delayMask;\n this.traceDelayAddr = writeAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'W';\n this.traceDelayValue = this.acc;\n this.delayRam[writeAddr] = this.acc;\n this.acc *= coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRAP(inst) {\n // WRAP addr, coeff\n // Delay[addr] = ACC; ACC = ACC * coeff + LR\n // Note: Pointer decrement happens at end of step, not here.\n // Encoding: CCCCCCCCCCCAAAAAAAAAAAAAAAA00011\n const addr = (inst >>> 5) & 0x7FFF;\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n const writeAddr = (this.delayPointer + addr) & this.delayMask;\n this.traceDelayAddr = writeAddr;\n this.traceDelayOffset = addr;\n this.traceDelayOp = 'W';\n this.traceDelayValue = this.acc;\n this.delayRam[writeAddr] = this.acc;\n // ACC = ACC * coeff + LR\n this.acc = this.acc * coeff + this.lr;\n this.acc = this.saturate(this.acc);\n }\n opRDAX(inst) {\n // RDAX reg, coeff\n // ACC = ACC + (Reg[reg] * coeff)\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00100\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const val = this.registers[reg];\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opWRAX(inst) {\n // WRAX reg, coeff\n // Reg[reg] = ACC; ACC = ACC * coeff\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00110\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc *= coeff;\n this.acc = this.saturate(this.acc);\n }\n opSOF(inst) {\n // SOF c, d\n // ACC = ACC * c + d\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01101\n const d = this.decodeS_10((inst >>> 5) & 0x7FF);\n const c = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.acc = this.acc * c + d;\n this.acc = this.saturate(this.acc);\n }\n opRMPA(inst) {\n // RMPA coeff\n // Read memory pointer. ADDR_PTR is mapped to REG24.\n // Encoding: CCCCCCCCCCC000000000001100000001 (or similar, coeff is top)\n const coeff = this.decodeS1_9((inst >>> 21) & 0x7FF);\n // Hardware truncates toward zero when converting the S.23 ADDR_PTR\n // to an integer offset. Math.floor would round tiny negative values\n // (~1e-20) to -1 and produce a parasitic read at delayPointer - 1,\n // which on this FV-1 architecture coincides with the chorus block's\n // simple_audio_output write from ~67 ms ago — creating a near-unity-\n // gain loop that takes hundreds of seconds to decay.\n const ptr = Math.trunc(this.registers[24] * this.delaySize);\n const readAddr = (this.delayPointer + ptr) & this.delayMask;\n const val = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = ptr;\n this.traceDelayOp = 'R';\n this.traceDelayValue = val;\n this.currentReadOffsets.add(ptr);\n this.lr = val;\n this.acc += val * coeff;\n this.acc = this.saturate(this.acc);\n }\n opMULX(inst) {\n // Encoding: 000000000000000000000AAAAAA01010\n const reg = (inst >>> 5) & 0x3F;\n this.acc = this.acc * this.registers[reg];\n this.acc = this.saturate(this.acc);\n }\n opLOG(inst) {\n // ACC = log2(|ACC|) * coeff + d\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01011\n const d = this.decodeS4_6((inst >>> 5) & 0x7FF);\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const val = Math.abs(this.acc);\n let logVal;\n if (val > 1.52587890625e-5) { // 2^-16, approx 96dB limit\n logVal = Math.log2(val);\n }\n else {\n logVal = -16.0;\n }\n // Result is in S4.19 format, so we divide by 16 to keep it in our S.23 float space\n this.acc = (logVal * coeff + d) / 16.0;\n this.acc = this.saturate(this.acc);\n }\n opEXP(inst) {\n // ACC = 2^ACC\n // Encoding: CCCCCCCCCCCCCCCCDDDDDDDDDDD01100\n const d = this.decodeS_10((inst >>> 5) & 0x7FF);\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const valS419 = this.acc * 16.0;\n // Result is linear S.23, which naturally fits our -1..1 float range\n this.acc = Math.pow(2, valS419) * coeff + d;\n this.acc = this.saturate(this.acc);\n }\n opRDFX(inst) {\n // RDFX reg, coeff\n // ACC = (REG[reg] - ACC) * coeff + REG[reg]\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00101\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const rx = this.registers[reg];\n this.acc = (this.acc - rx) * coeff + rx;\n this.acc = this.saturate(this.acc);\n }\n opMAXX(inst) {\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA01001\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n const a = Math.abs(this.acc);\n const b = Math.abs(this.registers[reg] * coeff);\n // MAXX result is always the magnitude (absolute value)\n this.acc = Math.max(a, b);\n this.acc = this.saturate(this.acc);\n }\n opSKP(inst) {\n // SKP condition, n\n // Encoding: CCCCCNNNNNN000000000000000010001\n const n = (inst >>> 21) & 0x3F;\n const flags = inst & 0xF8000000;\n let conditionMet = false;\n // Flags: RUN=0x80000000, ZRC=0x40000000, ZRO=0x20000000, GEZ=0x10000000, NEG=0x08000000\n if ((flags & 0x08000000) && this.acc < 0)\n conditionMet = true; // NEG\n if ((flags & 0x10000000) && this.acc >= 0)\n conditionMet = true; // GEZ\n if ((flags & 0x20000000) && this.acc === 0)\n conditionMet = true; // ZRO\n // ZRC (Zero Crossing) requires previous acc\n if ((flags & 0x40000000) && (this.acc * this.pacc < 0))\n conditionMet = true;\n // RUN flag: Skip if NOT first run\n if ((flags & 0x80000000) && !this.firstRun)\n conditionMet = true;\n return conditionMet ? n : 0;\n }\n opWRLX(inst) {\n // WRLX reg, coeff\n // Reg[reg] = ACC; ACC = (PACC - ACC) * coeff + PACC\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA01000\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc = (this.pacc - this.acc) * coeff + this.pacc;\n this.acc = this.saturate(this.acc);\n }\n opWRHX(inst) {\n // WRHX reg, coeff\n // Reg[reg] = ACC; ACC = PACC + ACC * coeff\n // Encoding: CCCCCCCCCCCCCCCC00000AAAAAA00111\n const reg = (inst >>> 5) & 0x3F;\n const coeff = this.decodeS1_14((inst >>> 16) & 0xFFFF);\n this.registers[reg] = this.acc;\n this.acc = this.pacc + this.acc * coeff;\n this.acc = this.saturate(this.acc);\n }\n opAND(inst) {\n // AND mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00001110\n const mask = (inst >>> 8) & 0xFFFFFF;\n // Convert ACC to 24-bit int, apply mask, convert back\n let iAcc = Math.floor(this.acc * 8388608.0); // 2^23\n iAcc &= mask;\n this.acc = iAcc / 8388608.0;\n }\n opOR(inst) {\n // OR mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00001111\n const mask = (inst >>> 8) & 0xFFFFFF;\n let iAcc = Math.floor(this.acc * 8388608.0);\n iAcc |= mask;\n this.acc = iAcc / 8388608.0;\n }\n opXOR(inst) {\n // XOR mask\n // Encoding: MMMMMMMMMMMMMMMMMMMMMMMM00010000\n const mask = (inst >>> 8) & 0xFFFFFF;\n let iAcc = Math.floor(this.acc * 8388608.0);\n iAcc ^= mask;\n this.acc = iAcc / 8388608.0;\n }\n opJAM(inst) {\n // JAM lfo\n // Encoding: 0000000000000000000000001N010011\n const lfo = (inst >>> 6) & 0x3; // 0=RMP0, 1=RMP1\n if (lfo === 0)\n this.rmp0 = 0;\n else if (lfo === 1)\n this.rmp1 = 0;\n }\n opWLDS(inst) {\n // WLDS lfo, freq, amp\n const lfoSelect = (inst >>> 29) & 0x1;\n const freqRaw = (inst >>> 20) & 0x1FF;\n const ampRaw = (inst >>> 5) & 0x7FFF;\n // Freq is an unsigned 9-bit value (0 to 511), amp is unsigned 15-bit (0 to 32767).\n // The FV-1 hardware uses power-of-2 fixed-point arithmetic (bit shifts),\n // so amplitude is divided by 2^15=32768, not 32767. Using 32767 causes the\n // computed delay address range to slightly exceed memory block boundaries.\n const f = freqRaw / 512.0;\n const a = ampRaw / 32768.0;\n if (lfoSelect === 0) {\n this.sin0_rate = f;\n this.sin0_range = a;\n this.registers[0] = f; // SIN0_RATE (reg0)\n this.registers[1] = a; // SIN0_RANGE (reg1)\n this.cos0 = -1.0;\n this.sin0 = 0.0;\n }\n else {\n this.sin1_rate = f;\n this.sin1_range = a;\n this.registers[2] = f; // SIN1_RATE (reg2)\n this.registers[3] = a; // SIN1_RANGE (reg3)\n this.cos1 = -1.0;\n this.sin1 = 0.0;\n }\n }\n opWLDR(inst) {\n // WLDR lfo, freq, amp\n // Encoding: 01NFFFFFFFFFFFFFFFF000000AA10010\n const lfoSelect = (inst >>> 29) & 0x1; // 0=RMP0, 1=RMP1\n // Freq is signed 16-bit\n let freq = (inst >>> 13) & 0xFFFF;\n if (freq & 0x8000)\n freq -= 65536;\n // Amp is a 2-bit code\n const ampCode = (inst >>> 5) & 0x3;\n const amp = 4096 >> ampCode; // 0->4096, 1->2048, 2->1024, 3->512\n // C logic: rate = f/16384.0, range = a/8192.0\n const f_val = freq / 16384.0;\n const a_val = amp / 8192.0;\n if (lfoSelect === 0) {\n this.rmp0_rate = f_val;\n this.rmp0_range = a_val;\n this.registers[4] = f_val; // RMP0_RATE (reg4)\n this.registers[5] = a_val; // RMP0_RANGE (reg5)\n this.rmp0 = 0.0;\n }\n else {\n this.rmp1_rate = f_val;\n this.rmp1_range = a_val;\n this.registers[6] = f_val; // RMP1_RATE (reg6)\n this.registers[7] = a_val; // RMP1_RANGE (reg7)\n this.rmp1 = 0.0;\n }\n }\n getLfoVal(flags, lfoSelect) {\n if (lfoSelect === 0) {\n return (flags & 1) ? this.cos0 : this.sin0;\n }\n else if (lfoSelect === 1) {\n return (flags & 1) ? this.cos1 : this.sin1;\n }\n else if (lfoSelect === 2) {\n return this.rmp0;\n }\n else {\n return this.rmp1;\n }\n }\n getLfoRange(lfoSelect) {\n if (lfoSelect === 0)\n return this.sin0_range;\n if (lfoSelect === 1)\n return this.sin1_range;\n if (lfoSelect === 2)\n return this.rmp0_range;\n return this.rmp1_range;\n }\n opCHO(inst) {\n const mode = (inst >>> 30) & 0x3;\n if (mode === 0) {\n this.opCHO_RDA(inst);\n }\n else if (mode === 2) {\n this.opCHO_SOF(inst);\n }\n else if (mode === 3) {\n this.opCHO_RDAL(inst);\n }\n }\n opCHO_RDA(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const offset = (inst >>> 5) & 0x7FFF;\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n let range = this.getLfoRange(lfoSelect);\n range *= 8192.0;\n if (flags & 2) { // cho_reg\n this.lfo = lfoIn;\n }\n let v = this.lfo;\n if (flags & 16) { // cho_rptr2\n v += 0.5;\n if (v >= 1.0)\n v -= 1.0;\n }\n if (flags & 8) { // cho_compa\n v = -v;\n }\n let index;\n let c;\n if (flags & 32) { // cho_na\n index = offset;\n c = Math.min(v, 1.0 - v);\n c = Math.max(0.0, Math.min(1.0, 4.0 * c - 0.5));\n }\n else {\n // Match the FV-1 / reference C: combine v*range with offset BEFORE\n // flooring. Separating them (e.g. trunc(v*range) + offset) gives the\n // wrong integer index when v*range is negative, because Math.trunc\n // rounds toward zero. Linear interpolation needs floor semantics.\n const addr = v * range + offset;\n index = Math.floor(addr);\n c = addr - index;\n }\n const readAddr = (this.delayPointer + index) & this.delayMask;\n this.lr = this.delayRam[readAddr];\n this.traceDelayAddr = readAddr;\n this.traceDelayOffset = index;\n this.traceDelayOp = 'R';\n this.traceDelayValue = this.lr;\n this.currentReadOffsets.add(index);\n if (flags & 4) { // cho_compc\n c = 1.0 - c;\n }\n this.acc += this.lr * c;\n this.acc = this.saturate(this.acc);\n }\n opCHO_SOF(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const coeffRaw = (inst >>> 5) & 0xFFFF;\n const coeff = this.decodeS_15(coeffRaw);\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n const range = this.getLfoRange(lfoSelect);\n if (flags & 2) { // cho_reg\n this.lfo = lfoIn;\n }\n let v = this.lfo;\n if (flags & 32) { // cho_na\n v = Math.min(v, 1.0 - v);\n v = Math.max(0.0, Math.min(1.0, 4.0 * v - 0.5));\n }\n else {\n v *= range;\n }\n if (flags & 4) { // cho_compc\n v = 1.0 - v;\n }\n this.acc = v * this.acc + coeff;\n this.acc = this.saturate(this.acc);\n }\n opCHO_RDAL(inst) {\n const flags = (inst >>> 24) & 0x3F;\n const lfoSelect = (inst >>> 21) & 0x3;\n const lfoIn = this.getLfoVal(flags, lfoSelect);\n this.acc = lfoIn;\n this.acc = this.saturate(this.acc);\n }\n // --- Debugging / State Access ---\n getPC() {\n return this.pc;\n }\n getProgSize() {\n return this.progSize;\n }\n setPC(pc) {\n this.pc = Math.max(0, Math.min(this.progSize - 1, pc));\n }\n setAcc(val) {\n this.acc = this.saturate(val);\n }\n setPacc(val) {\n this.pacc = this.saturate(val);\n }\n /**\n * Sets a register value with hardware-accurate saturation and quantization.\n * @param idx Register index (0-63)\n * @param val Raw value (float)\n */\n setRegister(idx, val) {\n if (idx < 0 || idx >= (32 + this.regCount))\n return;\n // POT registers (16, 17, 18) are 10-bit quantized 0..1\n if (idx >= 16 && idx <= 18) {\n val = Math.floor(Math.max(0, Math.min(0.9999999, val)) * 1024) / 1024;\n }\n else {\n // Other registers (ADC, DAC, User) are S.23 saturated\n val = this.saturate(val);\n }\n this.registers[idx] = val;\n }\n /**\n * Evaluates a string expression (register name, symbol, memory suffix).\n * @returns { result: string, value: number } or null\n */\n evaluateExpression(expr) {\n let expression = expr.trim().toUpperCase();\n // Handle suffixes ^ and #\n let suffix = \"\";\n if (expression.endsWith(\"^\")) {\n suffix = \"^\";\n expression = expression.slice(0, -1);\n }\n else if (expression.endsWith(\"#\")) {\n suffix = \"#\";\n expression = expression.slice(0, -1);\n }\n // 1. Check if it's a register name\n const state = this.getState();\n if (suffix === \"\" && state.registers[expression] !== undefined) {\n return { label: expression, value: state.registers[expression] };\n }\n // 2. Check if it's ACC/PACC\n if (suffix === \"\" && expression === \"ACC\") {\n return { label: \"ACC\", value: this.acc };\n }\n if (suffix === \"\" && expression === \"PACC\") {\n return { label: \"PACC\", value: this.pacc };\n }\n // 3. Check symbols (EQU)\n const sym = this.symbols.find(s => s.name.toUpperCase() === expression);\n if (sym && suffix === \"\") {\n const addr = parseInt(sym.value);\n if (!isNaN(addr) && addr >= 0 && addr <= 63) {\n return { label: `REG[${addr}] (${sym.name})`, value: this.registers[addr] };\n }\n }\n // 4. Check memories (MEM)\n const mem = this.memories.find(m => m.name.toUpperCase() === expression);\n if (mem && mem.start !== undefined) {\n let addr = mem.start;\n let typeLabel = \"\";\n if (suffix === \"^\") {\n addr = FV1Assembler.getMiddleAddr(mem.start, mem.size);\n typeLabel = \" (Middle)\";\n }\n else if (suffix === \"#\") {\n addr = FV1Assembler.getEndAddr(mem.start, mem.size, this.fv1AsmMemBug);\n typeLabel = \" (End)\";\n }\n if (addr >= 0 && addr < this.delaySize) {\n return { label: `MEM[${addr}] (${mem.name}${typeLabel})`, value: this.delayRam[addr] };\n }\n }\n // 5. Check DELAY[idx]\n if (suffix === \"\") {\n const delayMatch = expression.match(/^DELAY\\[(\\d+)\\]$/);\n if (delayMatch) {\n const idx = parseInt(delayMatch[1]);\n if (idx >= 0 && idx < this.delaySize) {\n return { label: `DELAY[${idx}]`, value: this.delayRam[idx] };\n }\n }\n }\n return null;\n }\n getState() {\n return {\n pc: this.pc,\n acc: this.acc,\n pacc: this.pacc,\n lr: this.lr,\n lfo: this.lfo,\n // Official Register Naming\n registers: Object.fromEntries(Array.from({ length: 32 + this.regCount }, (_, i) => {\n let name = `[${i}]`;\n if (i === 0)\n name = \"SIN0_RATE\";\n else if (i === 1)\n name = \"SIN0_RANGE\";\n else if (i === 2)\n name = \"SIN1_RATE\";\n else if (i === 3)\n name = \"SIN1_RANGE\";\n else if (i === 4)\n name = \"RMP0_RATE\";\n else if (i === 5)\n name = \"RMP0_RANGE\";\n else if (i === 6)\n name = \"RMP1_RATE\";\n else if (i === 7)\n name = \"RMP1_RANGE\";\n else if (i === 8)\n name = \"SIN0\";\n else if (i === 9)\n name = \"COS0\";\n else if (i === 10)\n name = \"SIN1\";\n else if (i === 11)\n name = \"COS1\";\n else if (i === 12)\n name = \"RMP0\";\n else if (i === 13)\n name = \"RMP1\";\n else if (i === 16)\n name = \"POT0\";\n else if (i === 17)\n name = \"POT1\";\n else if (i === 18)\n name = \"POT2\";\n else if (i === 20)\n name = \"ADCL\";\n else if (i === 21)\n name = \"ADCR\";\n else if (i === 22)\n name = \"DACL\";\n else if (i === 23)\n name = \"DACR\";\n else if (i === 24)\n name = \"ADDR_PTR\";\n else if (i >= 32 && i <= 63)\n name = `REG${i - 32}`;\n return [name, this.registers[i]];\n })),\n // Flags\n flags: {\n RUN: this.firstRun,\n ZRC: (this.acc * this.pacc < 0),\n ZRO: (this.acc === 0),\n GEZ: (this.acc >= 0),\n NEG: (this.acc < 0)\n },\n // LFO Internal positions\n lfoState: {\n sin0: this.sin0, cos0: this.cos0,\n sin1: this.sin1, cos1: this.cos1,\n rmp0: this.rmp0, rmp1: this.rmp1\n }\n };\n }\n getCycleCount() {\n return this.cycleCount;\n }\n getReadOffsets() {\n return Array.from(this.currentReadOffsets);\n }\n getRegisters() {\n return this.registers;\n }\n updateLFOs() {\n // Sync internal LFO modulations explicitly modified by WRAX or WRHX\n this.sin0_rate = this.registers[0];\n this.sin0_range = this.registers[1];\n this.sin1_rate = this.registers[2];\n this.sin1_range = this.registers[3];\n this.rmp0_rate = this.registers[4];\n this.rmp0_range = this.registers[5];\n this.rmp1_rate = this.registers[6];\n this.rmp1_range = this.registers[7];\n // C logic update_rmp0/1\n this.rmp0 -= this.rmp0_rate * (1.0 / 4096.0);\n while (this.rmp0 >= 1.0)\n this.rmp0 -= 1.0;\n while (this.rmp0 < 0.0)\n this.rmp0 += 1.0;\n this.rmp1 -= this.rmp1_rate * (1.0 / 4096.0);\n while (this.rmp1 >= 1.0)\n this.rmp1 -= 1.0;\n while (this.rmp1 < 0.0)\n this.rmp1 += 1.0;\n // SIN LFO update using coupled-form oscillator.\n // The FV-1 hardware updates cos first, then uses the updated cos for sin.\n // Clamp to [-1.0, MAX_ACC] to prevent float drift from exceeding the\n // FV-1's 24-bit fixed-point register range.\n const x0 = this.sin0_rate * (1.0 / 256.0);\n this.cos0 += x0 * this.sin0;\n this.sin0 -= x0 * this.cos0;\n this.sin0 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.sin0));\n this.cos0 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.cos0));\n const x1 = this.sin1_rate * (1.0 / 256.0);\n this.cos1 += x1 * this.sin1;\n this.sin1 -= x1 * this.cos1;\n this.sin1 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.sin1));\n this.cos1 = Math.max(FV1Simulator.MIN_ACC, Math.min(FV1Simulator.MAX_ACC, this.cos1));\n }\n updateStateRegisters() {\n // ONLY update accumulators here! Rate/Range is dictated by the program loop!\n // Writing registers[0..7] here would explicitly overwrite mid-frame WRAX modulations!\n // LFO State Accumulators\n this.registers[8] = this.sin0;\n this.registers[9] = this.cos0;\n this.registers[10] = this.sin1;\n this.registers[11] = this.cos1;\n this.registers[12] = this.rmp0;\n this.registers[13] = this.rmp1;\n }\n getDelayRam() {\n return this.delayRam;\n }\n // --- Helpers ---\n decodeS1_14(raw) {\n // 16 bits: 1 sign, 1 integer, 14 fractional\n if (raw & 0x8000)\n return (raw - 0x10000) / 16384.0;\n return raw / 16384.0;\n }\n decodeS1_9(raw) {\n // 11 bits: 1 sign, 1 integer, 9 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 512.0;\n return raw / 512.0;\n }\n decodeS_10(raw) {\n // 11 bits: 1 sign, 0 integer, 10 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 1024.0;\n return raw / 1024.0;\n }\n decodeS4_6(raw) {\n // 11 bits: 1 sign, 4 integer, 6 fractional\n if (raw & 0x400)\n return (raw - 0x800) / 64.0;\n return raw / 64.0;\n }\n decodeS_15(raw) {\n // 16 bits: 1 sign, 0 integer, 15 fractional\n if (raw & 0x8000)\n return (raw - 0x10000) / 32768.0;\n return raw / 32768.0;\n }\n saturate(val) {\n if (val > FV1Simulator.MAX_ACC)\n return FV1Simulator.MAX_ACC;\n if (val < FV1Simulator.MIN_ACC)\n return FV1Simulator.MIN_ACC;\n return val;\n }\n /**\n * Enable trace logging with a streaming writer callback.\n * Each row is emitted immediately via the writer — nothing is stored in memory.\n * @param writer Callback that receives each CSV row (including header).\n * @param maxCycles Maximum number of sample cycles to log (0 = unlimited).\n * @param onComplete Optional callback when trace auto-completes.\n */\n enableTrace(writer, maxCycles = 0, onComplete) {\n this.traceEnabled = true;\n this.traceWriter = writer;\n this.traceMaxCycles = maxCycles;\n this.traceCycle = 0;\n this.traceRowCount = 0;\n this.traceOnComplete = onComplete || null;\n // Emit CSV Header immediately (Reduced set for delay debugging)\n writer(`cycle,pc,opcode,delay_op,delay_offset,delay_addr,delay_ptr`);\n console.log(`[FV1 Trace] Logging enabled (maxCycles=${maxCycles || 'unlimited'})`);\n }\n /**\n * Disable trace logging.\n */\n disableTrace() {\n this.traceEnabled = false;\n this.traceWriter = null;\n console.log(`[FV1 Trace] Logging disabled. ${this.traceRowCount} rows written.`);\n }\n /**\n * Returns whether trace logging is currently active.\n */\n isTraceEnabled() {\n return this.traceEnabled;\n }\n /**\n * Returns the number of trace rows emitted so far.\n */\n getTraceRowCount() {\n return this.traceRowCount;\n }\n /**\n * Called at end-of-frame to advance the trace cycle counter.\n * If maxCycles is reached, trace is automatically disabled.\n */\n advanceTraceCycle() {\n if (!this.traceEnabled)\n return;\n this.traceCycle++;\n if (this.traceMaxCycles > 0 && this.traceCycle >= this.traceMaxCycles) {\n const onComplete = this.traceOnComplete;\n this.disableTrace();\n if (onComplete)\n onComplete();\n }\n }\n logTrace(pc, opcode, inst, accBefore) {\n if (!this.traceWriter)\n return;\n // FILTER: Only log delay memory operations\n if (this.traceDelayOp === '')\n return;\n const opName = FV1Simulator.OPCODE_NAMES[opcode] || `?${opcode.toString(16)}`;\n // Resolve CHO sub-type\n let fullOpName = opName;\n if (opcode === 0x14) {\n const mode = (inst >>> 30) & 0x3;\n if (mode === 0)\n fullOpName = 'CHO_RDA';\n else if (mode === 2) {\n // CHO_SOF does not access delay RAM, so we filter it out\n return;\n }\n else if (mode === 3)\n fullOpName = 'CHO_RDAL';\n }\n else if (opcode === 0x12) {\n // WLDS/WLDR do not access delay RAM directly in a way we track here\n return;\n }\n const row = `${this.traceCycle},${pc},${fullOpName},` +\n `${this.traceDelayOp},${this.traceDelayOp !== '' ? this.traceDelayOffset : ''},${this.traceDelayAddr >= 0 ? this.traceDelayAddr : ''},${this.delayPointer}`;\n this.traceWriter(row);\n this.traceRowCount++;\n }\n}\nFV1Simulator.MAX_ACC = 1.0 - (1.0 / 8388608.0); // 24-bit S.23: 1 - 2^-23\nFV1Simulator.MIN_ACC = -FV1Simulator.MAX_ACC; // Symmetrically bound to prevent limits bias\n// --- Trace Logging System ---\nFV1Simulator.OPCODE_NAMES = {\n 0x00: 'RDA', 0x01: 'RMPA', 0x02: 'WRA', 0x03: 'WRAP',\n 0x04: 'RDAX', 0x05: 'RDFX', 0x06: 'WRAX', 0x07: 'WRHX',\n 0x08: 'WRLX', 0x09: 'MAXX', 0x0A: 'MULX', 0x0B: 'LOG',\n 0x0C: 'EXP', 0x0D: 'SOF', 0x0E: 'AND', 0x0F: 'OR',\n 0x10: 'XOR', 0x11: 'SKP', 0x12: 'WLDx', 0x13: 'JAM',\n 0x14: 'CHO'\n};\n//# sourceMappingURL=FV1Simulator.js.map","import { FV1Simulator } from '@audiofab-io/fv1-core'\n\ntype ChannelMode = 'mono' | 'stereo'\n\nclass FV1Processor extends AudioWorkletProcessor {\n private simulator = new FV1Simulator()\n private pot = [0.5, 0.5, 0.5]\n private bypassed = false\n /** Mono emulates the current Easy Spin hardware (only the left DAC is wired\n * to both jack tips). Stereo plays the FV-1's native left/right outputs. */\n private channelMode: ChannelMode = 'mono'\n\n constructor() {\n super()\n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case 'loadProgram':\n this.simulator.loadProgram(new Uint32Array(data.machineCode))\n break\n case 'setPot':\n this.pot[data.index] = data.value\n break\n case 'bypass':\n this.bypassed = data.active\n break\n case 'setChannelMode':\n this.channelMode = data.mode === 'stereo' ? 'stereo' : 'mono'\n break\n }\n }\n }\n\n process(inputs: Float32Array[][], outputs: Float32Array[][]): boolean {\n const input = inputs[0]\n const output = outputs[0]\n if (!input?.length || !output?.length) return true\n\n const inL = input[0]\n const inR = input[1] ?? inL\n const outL = output[0]\n const outR = output[1] ?? outL\n\n if (this.bypassed) {\n outL.set(inL)\n if (output[1]) outR.set(inR)\n return true\n }\n\n this.simulator.processBlock(inL, inR, outL, outR,\n this.pot[0], this.pot[1], this.pot[2])\n\n // Mono: mirror the left (FV-1 DACL) output to the right channel so the\n // simulator matches the current mono pedal, where only DACL drives the jack.\n if (this.channelMode === 'mono' && output[1]) {\n outR.set(outL)\n }\n return true\n }\n}\n\nregisterProcessor('fv1-processor', FV1Processor)\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@audiofab-io/easy-spin-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Shared React components and FV-1 simulation runtime for Audiofab's Easy Spin pedal — used by the Easy Spin web tool and the FV-1 VS Code extension.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"react-dom": "^19.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@audiofab-io/fv1-core": "^0.6.
|
|
45
|
+
"@audiofab-io/fv1-core": "^0.6.5",
|
|
46
46
|
"@tailwindcss/cli": "^4.2.2",
|
|
47
47
|
"@tailwindcss/vite": "^4.2.2",
|
|
48
48
|
"@types/react": "^19.2.14",
|