@ngx-telly/plugin-vu-meter
Version:
Telly - Vu meter plugin
1 lines • 26.9 kB
Source Map (JSON)
{"version":3,"file":"ngx-telly-plugin-vu-meter.mjs","sources":["../../../../libs/plugin-vu-meter/src/lib/vu-meter.service.ts","../../../../libs/plugin-vu-meter/src/lib/components/telly-vu-meter/telly-vu-meter.component.ts","../../../../libs/plugin-vu-meter/src/lib/components/telly-vu-meter/telly-vu-meter.component.html","../../../../libs/plugin-vu-meter/src/lib/icons.ts","../../../../libs/plugin-vu-meter/src/lib/components/telly-vu-meter-toggle/telly-vu-meter-toggle.component.ts","../../../../libs/plugin-vu-meter/src/lib/components/telly-vu-meter-toggle/telly-vu-meter-toggle.component.html","../../../../libs/plugin-vu-meter/src/provider.ts","../../../../libs/plugin-vu-meter/src/ngx-telly-plugin-vu-meter.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Subject } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class VuMeterService {\n show$ = new BehaviorSubject<boolean>(false);\n reconfigure$ = new Subject<void>();\n\n toggle() {\n this.show$.next(!this.show$.value);\n }\n\n reconfigure() {\n this.reconfigure$.next();\n }\n\n isVisible() {\n return this.show$.value;\n }\n}\n","import {\n Component,\n HostBinding,\n inject,\n Input,\n OnChanges,\n OnDestroy,\n OnInit,\n signal,\n SimpleChanges,\n} from '@angular/core';\nimport { VuMeterService } from '../../vu-meter.service';\nimport { PlayerComponent } from '@ngx-telly/player';\nimport { map, Subscription, tap } from 'rxjs';\nimport { AsyncPipe, NgFor, NgIf } from '@angular/common';\n\nexport interface Level {\n channel: string;\n rms: number;\n db: number;\n normalized: number;\n peak: number;\n}\n\ninterface AudioAnalysisState {\n isAnalyzing: boolean;\n animationFrame?: number;\n peakHoldValues: number[];\n peakHoldTimers: number[];\n}\n\ninterface AudioNodes {\n context?: AudioContext;\n source?: MediaElementAudioSourceNode;\n splitter?: ChannelSplitterNode;\n analyzers: AnalyserNode[];\n dataArrays: Float32Array[];\n}\n\n@Component({\n selector: 'telly-vu-meter',\n imports: [NgIf, NgFor, AsyncPipe],\n templateUrl: './telly-vu-meter.component.html',\n styleUrl: './telly-vu-meter.component.css'\n})\nexport class TellyVuMeterComponent implements OnInit, OnDestroy, OnChanges {\n @HostBinding('style.display')\n display = 'none';\n\n @Input() fftSize = 1024;\n @Input() channelCount = 2;\n @Input() channelNames: string[] = [];\n @Input() peakHoldTime = 300;\n @Input() peakDecayRate = 0.1;\n @Input() peakAccelerationFactor = 4;\n @Input() peakSmoothingFactor = 1;\n @Input() updateRateMs = 40;\n\n readonly service = inject(VuMeterService);\n readonly player = inject(PlayerComponent);\n\n private readonly subscription = new Subscription();\n private readonly audioNodes: AudioNodes = {\n context: undefined,\n splitter: undefined,\n source: undefined,\n analyzers: [],\n dataArrays: [],\n };\n private readonly analysisState: AudioAnalysisState = {\n isAnalyzing: false,\n peakHoldValues: [],\n peakHoldTimers: [],\n };\n\n readonly levels = signal<Level[]>([]);\n readonly reconfiguring = signal(false);\n\n ngOnInit(): void {\n this.setupVisibilitySubscription();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['channelCount'] && !changes['channelCount'].isFirstChange()) {\n this.updateChannelCount(changes['channelCount'].currentValue);\n }\n }\n\n ngOnDestroy(): void {\n this.stopAnalysis();\n this.disconnectAudioGraph();\n this.cleanupAudioContext();\n this.subscription.unsubscribe();\n }\n\n trackByChannel(index: number, level: Level): string {\n return level.channel;\n }\n\n private setupVisibilitySubscription(): void {\n this.subscription.add(\n this.service.show$\n .pipe(\n tap((show) => this.player.media.indicate(`VU Meter ${show ? 'ON' : 'OFF'}`)),\n tap((show) => {\n if (show) {\n this.initializeAudioAndStartAnalysis();\n } else {\n this.stopAnalysis();\n this.disconnectAudioGraph();\n }\n }),\n map((show) => (show ? 'flex' : 'none'))\n )\n .subscribe((display) => (this.display = display))\n );\n\n this.subscription.add(this.service.reconfigure$.subscribe(() => this.reconfigure()));\n }\n\n private reconfigure() {\n this.reconfiguring.set(true);\n this.stopAnalysis();\n this.disconnectAudioGraph();\n\n setTimeout(() => {\n this.reconfiguring.set(false);\n this.initializeAudioAndStartAnalysis();\n }, 1000);\n }\n\n private updateChannelCount(newCount: number): void {\n this.channelCount = newCount;\n\n if (this.audioNodes.source && this.audioNodes.context) {\n const wasAnalyzing = this.analysisState.isAnalyzing;\n this.stopAnalysis();\n this.disconnectAudioGraph();\n\n if (wasAnalyzing) {\n this.connectAudioGraphAndStartAnalysis();\n }\n }\n }\n\n private initializeAudioAndStartAnalysis(): void {\n if (!this.audioNodes.context) {\n this.initializeAudioContext()\n .then(() => {\n this.connectAudioGraphAndStartAnalysis();\n })\n .catch((error) => {\n console.error('Failed to initialize audio for VU meter:', error);\n });\n } else {\n this.connectAudioGraphAndStartAnalysis();\n }\n }\n\n private async initializeAudioContext(): Promise<void> {\n if (this.audioNodes.context) {\n return;\n }\n\n this.audioNodes.context = new AudioContext();\n\n await this.audioNodes.context.resume();\n\n if (!this.audioNodes.source && this.audioNodes.context) {\n this.audioNodes.source = this.audioNodes.context.createMediaElementSource(this.player.video.nativeElement);\n this.audioNodes.source.connect(this.audioNodes.context.destination);\n }\n }\n\n private connectAudioGraphAndStartAnalysis(): void {\n if (!this.audioNodes.context || !this.audioNodes.source) {\n console.warn('Audio context or source not initialized');\n return;\n }\n\n this.buildAudioGraph();\n this.startAnalysis();\n }\n\n private buildAudioGraph(): void {\n if (!this.audioNodes.context || !this.audioNodes.source) return;\n\n this.audioNodes.splitter = this.audioNodes.context.createChannelSplitter(this.channelCount);\n\n this.audioNodes.analyzers = Array(this.channelCount)\n .fill(0)\n .map(() => {\n const analyzer = this.audioNodes.context!.createAnalyser();\n analyzer.fftSize = this.fftSize;\n analyzer.smoothingTimeConstant = 0.8;\n return analyzer;\n });\n\n this.audioNodes.source.connect(this.audioNodes.splitter);\n this.audioNodes.analyzers.forEach((analyzer, i) => {\n this.audioNodes.splitter!.connect(analyzer, i);\n });\n\n this.audioNodes.dataArrays = this.audioNodes.analyzers.map((analyzer) => new Float32Array(analyzer.fftSize));\n }\n\n private startAnalysis(): void {\n if (this.analysisState.isAnalyzing) {\n return;\n }\n\n this.analysisState.isAnalyzing = true;\n this.analysisState.peakHoldValues = new Array(this.channelCount).fill(0);\n this.analysisState.peakHoldTimers = new Array(this.channelCount).fill(0);\n\n const channelNames = this.getChannelNames(this.channelCount);\n\n this.runAnalysisLoop(channelNames);\n }\n\n private runAnalysisLoop(channelNames: string[]): void {\n if (!this.analysisState.isAnalyzing) {\n return;\n }\n\n this.audioNodes.analyzers.forEach((analyzer, i) => {\n analyzer.getFloatTimeDomainData(this.audioNodes.dataArrays[i]);\n });\n\n const levels = this.audioNodes.dataArrays.map((dataArray, i) =>\n this.calculateChannelLevel(dataArray, channelNames[i], i)\n );\n\n this.levels.set(levels);\n\n this.analysisState.animationFrame = requestAnimationFrame(() => {\n setTimeout(() => this.runAnalysisLoop(channelNames), this.updateRateMs);\n });\n }\n\n private calculateChannelLevel(dataArray: Float32Array, channelName: string, channelIndex: number): Level {\n let sumSquares = 0;\n for (let i = 0; i < dataArray.length; i++) {\n sumSquares += dataArray[i] * dataArray[i];\n }\n\n const rms = Math.sqrt(sumSquares / dataArray.length);\n const db = Math.round(20 * Math.log10(Math.max(rms, 0.0000001)));\n const normalized = Math.max(0, Math.min(1, (db + 60) / 60));\n\n const peak = this.updatePeakHold(normalized, channelIndex);\n\n return {\n channel: channelName,\n rms,\n db,\n normalized,\n peak,\n };\n }\n\n private updatePeakHold(currentLevel: number, channelIndex: number): number {\n if (currentLevel > this.analysisState.peakHoldValues[channelIndex]) {\n this.analysisState.peakHoldValues[channelIndex] = currentLevel;\n this.analysisState.peakHoldTimers[channelIndex] = Date.now();\n } else {\n const timeSinceLastPeak = Date.now() - this.analysisState.peakHoldTimers[channelIndex];\n\n if (timeSinceLastPeak > this.peakHoldTime) {\n const decayTime = timeSinceLastPeak - this.peakHoldTime;\n const decaySeconds = decayTime / 1000;\n\n const smoothingFactor = Math.min(decaySeconds, 1);\n const currentDecayRate =\n this.peakDecayRate * Math.pow(this.peakAccelerationFactor, decaySeconds) * smoothingFactor;\n\n this.analysisState.peakHoldValues[channelIndex] = Math.max(\n 0,\n this.analysisState.peakHoldValues[channelIndex] - currentDecayRate\n );\n }\n }\n\n return this.analysisState.peakHoldValues[channelIndex];\n }\n\n private stopAnalysis(): void {\n this.analysisState.isAnalyzing = false;\n\n if (this.analysisState.animationFrame) {\n cancelAnimationFrame(this.analysisState.animationFrame);\n this.analysisState.animationFrame = undefined;\n }\n }\n\n private getChannelNames(count: number): string[] {\n if (this.channelNames.length) {\n return this.channelNames;\n }\n\n switch (count) {\n case 1:\n return ['M'];\n case 2:\n return ['L', 'R'];\n case 3:\n return ['L', 'R', 'LFE'];\n case 4:\n return ['FL', 'FR', 'SL', 'SR'];\n case 5:\n return ['FL', 'FR', 'C', 'SL', 'SR'];\n case 6:\n return ['FL', 'FR', 'C', 'LFE', 'SL', 'SR'];\n case 7:\n return ['FL', 'FR', 'C', 'LFE', 'SL', 'SR', 'BC'];\n case 8:\n return ['FL', 'FR', 'C', 'LFE', 'SL', 'SR', 'BL', 'BR'];\n default:\n return Array(count)\n .fill(0)\n .map((_, i) => `C${i + 1}`);\n }\n }\n\n private disconnectAudioGraph(): void {\n if (this.audioNodes.splitter) {\n this.audioNodes.analyzers.forEach((analyzer) => {\n analyzer.disconnect();\n });\n this.audioNodes.splitter.disconnect();\n }\n\n this.audioNodes.splitter = undefined;\n this.audioNodes.analyzers = [];\n this.audioNodes.dataArrays = [];\n }\n\n private cleanupAudioContext(): void {\n if (this.audioNodes.source && this.audioNodes.context) {\n this.audioNodes.source.disconnect();\n }\n\n if (this.audioNodes.context) {\n this.audioNodes.context.suspend().catch((err) => {\n console.error('Error suspending audio context:', err);\n });\n }\n\n this.audioNodes.source = undefined;\n this.audioNodes.context = undefined;\n }\n}\n","<ng-container *ngIf=\"(service.show$ | async) && !reconfiguring()\">\n <div class=\"vu-meter-container\">\n <div class=\"vu-meter-panel\">\n <div class=\"vu-meter-channels\">\n <div class=\"channel-meter\" *ngFor=\"let level of levels(); trackBy: trackByChannel\">\n <div class=\"channel-label\">{{ level.channel }}</div>\n <div class=\"meter-container\">\n <div class=\"meter-background\">\n <div class=\"meter-segment green\"></div>\n <div class=\"meter-segment green\"></div>\n <div class=\"meter-segment green\"></div>\n <div class=\"meter-segment green\"></div>\n <div class=\"meter-segment yellow\"></div>\n <div class=\"meter-segment yellow\"></div>\n <div class=\"meter-segment red\"></div>\n <div class=\"meter-segment red\"></div>\n </div>\n <div class=\"meter-background-full\"\n [style.clip-path]=\"'polygon(0 100%, 100% 100%, 100% ' + (100 - level.normalized * 100) + '%, 0 ' + (100 - level.normalized * 100) + '%)'\">\n <div class=\"meter-segment-full green\"></div>\n <div class=\"meter-segment-full green\"></div>\n <div class=\"meter-segment-full green\"></div>\n <div class=\"meter-segment-full green\"></div>\n <div class=\"meter-segment-full yellow\"></div>\n <div class=\"meter-segment-full yellow\"></div>\n <div class=\"meter-segment-full red\"></div>\n <div class=\"meter-segment-full red\"></div>\n </div>\n <div class=\"peak-indicator\"\n [style.bottom.%]=\"level.peak * 100\"\n [class.visible]=\"level.peak > 0.01\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"reconfiguring()\">\n <div class=\"vu-meter-container\">\n <div class=\"vu-meter-panel\">\n <div class=\"vu-meter-channels\">\n <div class=\"channel-meter\">\n <div class=\"loading-info\">\n <div>Audio</div>\n <div>Loading</div>\n <div class=\"loading-animation\">\n <div class=\"spinner\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n","export const equalizer = 'M10,20H14V4H10V20M4,20H8V12H4V20M16,9V20H20V9H16Z';\nexport const gauge =\n 'M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4A8,8 0 0,1 20,12C20,14.4 19,16.5 17.3,18C15.9,16.7 14,16 12,16C10,16 8.2,16.7 6.7,18C5,16.5 4,14.4 4,12A8,8 0 0,1 12,4M14,5.89C13.62,5.9 13.26,6.15 13.1,6.54L11.81,9.77L11.71,10C11,10.13 10.41,10.6 10.14,11.26C9.73,12.29 10.23,13.45 11.26,13.86C12.29,14.27 13.45,13.77 13.86,12.74C14.12,12.08 14,11.32 13.57,10.76L13.67,10.5L14.96,7.29L14.97,7.26C15.17,6.75 14.92,6.17 14.41,5.96C14.28,5.91 14.15,5.89 14,5.89M10,6A1,1 0 0,0 9,7A1,1 0 0,0 10,8A1,1 0 0,0 11,7A1,1 0 0,0 10,6M7,9A1,1 0 0,0 6,10A1,1 0 0,0 7,11A1,1 0 0,0 8,10A1,1 0 0,0 7,9M17,9A1,1 0 0,0 16,10A1,1 0 0,0 17,11A1,1 0 0,0 18,10A1,1 0 0,0 17,9';\n","import { Component, HostBinding, HostListener, inject, input } from '@angular/core';\nimport { VuMeterService } from '../../vu-meter.service';\nimport { gauge } from '../../icons';\n\n@Component({\n selector: 'telly-vu-meter-toggle',\n imports: [],\n templateUrl: './telly-vu-meter-toggle.component.html',\n styleUrl: './telly-vu-meter-toggle.component.css'\n})\nexport class TellyVuMeterToggleComponent {\n icon = input(gauge);\n size = input('1.4rem');\n\n service = inject(VuMeterService);\n\n @HostBinding('attr.tip') title = 'VU Meter';\n\n @HostListener('pointerdown')\n onClick(): void {\n this.service.toggle();\n }\n}\n","<svg\n viewBox=\"0 0 24 24\"\n [style.width]=\"size()\"\n>\n <path\n fill=\"white\"\n [attr.d]=\"icon()\"\n />\n</svg>\n\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { VuMeterService } from './lib/vu-meter.service';\n\nexport function provideTellyVuMeter(): EnvironmentProviders {\n return makeEnvironmentProviders([VuMeterService]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}