import { Log } from "../../log" ; import { Serializeable , MemBuffer } from "../../misc/membuffer" ; /**
 * The buffer exchanged with the zsim simulator webview.
 * It contains only the lengths for the stats changes of the beeper.
 */ export interface BeeperBuffer { totalLength : number ; startValue : boolean ; buffer : Uint16Array ; bufferLen : number ; } /**
 * ZX beeper audio simulation.
 */ export class ZxBeeper implements Serializeable { protected lastBeeperValue = true ; protected lastBeeperTstates = 0 ; protected lastBeeperIndex = 0 ; protected lastBeeperTimeIndex = 0 ; protected startBeeperValue = true ; protected beeperLenBuffer : Uint16Array ; protected cpuFrequency : number ; protected sampleRate : number ; param cpuFrequency param sampleRate param updateFrequency param passedTstates constructor ( cpuFrequency , sampleRate , updateFrequency , passedTstates = 0 ) { this . sampleRate = sampleRate ; const bufferSize = 2 * Math . floor ( sampleRate / updateFrequency ) ; this . beeperLenBuffer = new Uint16Array ( bufferSize ) ; this . lastBeeperIndex = 0 ; this . lastBeeperTstates = passedTstates ; this . lastBeeperValue = true ; this . cpuFrequency = cpuFrequency ; } returns public getCurrentBeeperValue ( ) { return ( this . lastBeeperValue ) ? 1 : 0 ; } param passedTstates param on public writeBeeper ( passedTstates , on ) { if ( on != this . lastBeeperValue ) { this . setLastBeeperValue ( passedTstates ) ; this . lastBeeperValue = on ; } } param passedTstates protected setLastBeeperValue ( passedTstates ) { const time = ( passedTstates - this . lastBeeperTstates ) / this . cpuFrequency ; let timeIndex = Math . floor ( time * this . sampleRate ) ; if ( timeIndex >= this . beeperLenBuffer . length ) { return ; } let length = timeIndex - this . lastBeeperTimeIndex ; if ( length == 0 ) { if ( this . lastBeeperIndex > 0 ) { this . lastBeeperIndex -- ; this . lastBeeperTimeIndex -= this . beeperLenBuffer [ this . lastBeeperIndex ] ; } if ( this . lastBeeperTimeIndex == 0 ) { this . startBeeperValue = ! this . lastBeeperValue ; } return ; } this . beeperLenBuffer [ this . lastBeeperIndex ++ ] = length ; this . lastBeeperTimeIndex = timeIndex ; Log . log ( 'setLastBeeperValue: end' ) ; } param passedTstates returns public getBeeperBuffer ( passedTstates ) { Log . log ( 'getBeeperBuffer: start.' ) ; const time = ( passedTstates - this . lastBeeperTstates ) / this . cpuFrequency ; let timeIndex = Math . floor ( time * this . sampleRate ) ; if ( timeIndex >= this . beeperLenBuffer . length ) { timeIndex = this . beeperLenBuffer . length ; } let length = timeIndex - this . lastBeeperTimeIndex ; if ( length > 0 ) this . beeperLenBuffer [ this . lastBeeperIndex ++ ] = length ; const buffer = new Uint16Array ( this . lastBeeperIndex ) ; buffer . set ( this . beeperLenBuffer . slice ( 0 , this . lastBeeperIndex ) , 0 ) ; let totalLength = 0 ; for ( const len of buffer ) { totalLength += len ; } this . lastBeeperTstates = passedTstates ; this . lastBeeperIndex = 0 ; this . lastBeeperTimeIndex = 0 ; const resultStartValue = this . startBeeperValue ; this . startBeeperValue = this . lastBeeperValue ; return { totalLength , startValue : resultStartValue , buffer , bufferLen : buffer . length } ; } /**
     * Returns the size the serialized object would consume.
     */ public getSerializedSize ( ) { const memBuffer = new MemBuffer ( ) ; this . serialize ( memBuffer ) ; const size = memBuffer . getSize ( ) ; return size ; } /**
     * Serializes the object.
     * Basically the last beeper value.
     */ public serialize ( memBuffer ) { memBuffer . writeBoolean ( this . lastBeeperValue ) ; memBuffer . writeNumber ( this . lastBeeperTstates ) ; } /**
     * Deserializes the object.
     */ public deserialize ( memBuffer ) { this . lastBeeperValue = memBuffer . readBoolean ( ) ; this . lastBeeperTstates = memBuffer . readNumber ( ) ; this . lastBeeperIndex = 0 ; this . lastBeeperTstates = 0 ; } }