import { PermissionsService , PermissionStatus } from '@airgap/angular-core' ; import { Injectable } from '@angular/core' ; import { Platform } from '@ionic/angular' ; import { Observable } from 'rxjs' ; import entropyCalculatorWorkerJS from '../../../assets/workers/entropyCalculatorWorker' ; import { Entropy , IEntropyGenerator } from '../entropy/IEntropyGenerator' ; declare var window ; const blobURL = window . URL . createObjectURL ( new Blob ( [ entropyCalculatorWorkerJS ] ) ) ; const entropyCalculatorWorker = new Worker ( blobURL ) ; @ Injectable ( { providedIn : 'root' } ) export class AudioNativeService implements IEntropyGenerator { private readonly ENTROPY_SIZE : number = 4096 ; private collectedEntropyPercentage : number = 0 ; private handler ; private readonly entropyObservable : Observable < Entropy > ; constructor ( private readonly platform , private readonly permissionsService ) { this . entropyObservable = Observable . create ( ( observer ) => { entropyCalculatorWorker . onmessage = ( event ) => { this . collectedEntropyPercentage += event . data . entropyMeasure ; observer . next ( { entropyHex : event . data . entropyHex } ) ; } ; this . handler = ( audioStream ) => { const buffer1 = this . arrayBufferFromIntArray ( audioStream . data ) ; entropyCalculatorWorker . postMessage ( { entropyBuffer : buffer1 } , [ buffer1 ] ) ; } ; } ) ; } public async start ( ) { this . collectedEntropyPercentage = 0 ; await this . platform . ready ( ) ; const permissionStatus = await this . permissionsService . hasMicrophonePermission ( ) ; if ( permissionStatus !== PermissionStatus . GRANTED ) { return ; } window . audioinput . start ( { bufferSize : this . ENTROPY_SIZE } ) ; setTimeout ( ( ) => { window . addEventListener ( 'audioinput' , this . handler ) ; } , 1000 ) ; console . log ( 'audioinput created.' ) ; } public stop ( ) { return new Promise ( ( resolve ) => { console . log ( 'removed audioinput listener' ) ; window . audioinput . stop ( ) ; window . removeEventListener ( 'audioinput' , this . handler ) ; resolve ( ) ; } ) ; } public getEntropyUpdateObservable ( ) { return this . entropyObservable ; } private arrayBufferFromIntArray ( array ) { const buffer = new ArrayBuffer ( array . length * 2 ) ; const bufView = new Uint8Array ( buffer ) ; for ( let i = 0 ; i < array . length ; i ++ ) { bufView [ i ] = Math . abs ( array [ i ] * 10000 ) ; } return buffer ; } public getCollectedEntropyPercentage ( ) { return this . collectedEntropyPercentage / 150 ; } }