const frameSize = 256 * 240 ; const maskSize = frameSize / 8 ; const frameCountReset = 180 ; const resetable = false ; export default class OutputProcessor { private frameCount : number ; private currentFrame : number [ ] ; private drawingFrame : number [ ] ; private audioSamples : number [ ] ; private pixels : number [ ] ; private mask : boolean [ ] ; private flushIt = false ; constructor ( ) { this . frameCount = 0 ; this . currentFrame = new Array ( frameSize ) ; this . drawingFrame = new Array ( frameSize ) ; this . audioSamples = [ ] ; this . pixels = new Array ( frameSize ) ; this . mask = new Array ( frameSize ) ; } process ( data ) { if ( this . flushIt ) { let frame = data . video ; for ( let i = 0 ; i < frameSize ; i += 1 ) { this . drawingFrame [ i ] = 0x00ffffff & frame [ i ] ; } this . flushIt = false ; let pixels = this . getPixels ( ) ; let mask = pixels . length < frameSize ? this . getMask ( ) : new ArrayBuffer ( 0 ) ; let pair = this . getPalette ( pixels ) ; return { mask : pixels . length < frameSize ? this . getMask ( ) : new ArrayBuffer ( 0 ) , palette : pair . palette , frame : this . getFrame ( pixels , pair . map ) , audio8 : this . getAudio ( this . audioSamples . length ? this . audioSamples . concat ( data . audio ) : data . audio ) } ; } else { this . flushIt = true ; let temp = this . currentFrame ; this . currentFrame = this . drawingFrame ; this . drawingFrame = temp ; this . audioSamples = data . audio || [ ] ; return null ; } } private getPixels ( ) { let pixels ; if ( this . frameCount ) { pixels = this . pixels ; let mask = this . mask ; let count = 0 ; for ( let i = 0 ; i < frameSize ; i += 1 ) { let pixel = this . drawingFrame [ i ] ; if ( pixel != this . currentFrame [ i ] ) { pixels [ count ] = pixel ; count += 1 ; mask [ i ] = true ; } else { mask [ i ] = false ; } } pixels = pixels . slice ( 0 , count ) ; } else { pixels = this . drawingFrame ; } if ( resetable ) { this . frameCount += 1 ; if ( this . frameCount >= frameCountReset ) { this . frameCount = 0 ; } } else { this . frameCount = 1 ; } { let temp = this . currentFrame ; this . currentFrame = this . drawingFrame ; this . drawingFrame = temp ; } return pixels ; } private getMask ( ) { let bytes = new Uint8Array ( maskSize ) ; let mask = this . mask ; for ( let i = 0 ; i < frameSize ; i += 8 ) { let byte = 0 ; if ( mask [ i ] ) byte |= 1 ; if ( mask [ i + 1 ] ) byte |= 1 << 1 ; if ( mask [ i + 2 ] ) byte |= 1 << 2 ; if ( mask [ i + 3 ] ) byte |= 1 << 3 ; if ( mask [ i + 4 ] ) byte |= 1 << 4 ; if ( mask [ i + 5 ] ) byte |= 1 << 5 ; if ( mask [ i + 6 ] ) byte |= 1 << 6 ; if ( mask [ i + 7 ] ) byte |= 1 << 7 ; bytes [ i >> 3 ] = byte ; } return bytes . buffer ; } private getPalette ( pixels ) { let colors = [ ] ; let hasColor = { } ; for ( let i = 0 ; i < pixels . length ; i += 1 ) { let color = pixels [ i ] ; if ( ! hasColor [ color ] ) { hasColor [ color ] = true ; colors . push ( color ) ; } } colors . sort ( ) ; let palette = new Uint8Array ( colors . length * 3 ) ; let map = { } ; for ( let i = 0 , j = 0 ; i < colors . length ; i += 1 ) { let color = colors [ i ] ; map [ color ] = i ; palette [ j ++ ] = color & 0xFF ; palette [ j ++ ] = ( color >> 8 ) & 0xFF ; palette [ j ++ ] = ( color >> 16 ) & 0xFF ; } return { palette : palette . buffer , map : map } ; } private getFrame ( pixles , map ) { let frame = new Uint8Array ( pixles . length ) ; for ( let i = 0 ; i < pixles . length ; i += 1 ) { frame [ i ] = map [ pixles [ i ] ] ; } return frame . buffer ; } private getAudio ( samples ) { let audio8 = new Uint8Array ( samples . length ) ; for ( let i = 0 ; i < samples . length ; i += 1 ) { let sample = ( samples [ i ] + 1 ) / 2.0 ; audio8 [ i ] = Math . floor ( sample * 255 ) ; } return audio8 . buffer ; } } export interface OutputData { mask : ArrayBuffer ; palette : ArrayBuffer ; frame : ArrayBuffer ; audio8 : ArrayBuffer ; } type ColorMap = { [ color ] : number ; } ;