Skip to content

Commit

Permalink
Emit volume changes
Browse files Browse the repository at this point in the history
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
  • Loading branch information
SimonBrandner committed Aug 19, 2021
1 parent e25a649 commit 6904f6b
Showing 1 changed file with 71 additions and 1 deletion.
72 changes: 71 additions & 1 deletion src/webrtc/callFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ import { SDPStreamMetadataPurpose } from "./callEventTypes";
import { MatrixClient } from "../client";
import { RoomMember } from "../models/room-member";

const POLLING_INTERVAL = 250; // ms

export enum CallFeedEvent {
NewStream = "new_stream",
MuteStateChanged = "mute_state_changed"
MuteStateChanged = "mute_state_changed",
VolumeChanged = "volume_changed",
}

export class CallFeed extends EventEmitter {
private measuringVolumeActivity = false;
private audioContext: AudioContext;
private analyser: AnalyserNode;
private frequencyBinCount: Float32Array;

constructor(
public stream: MediaStream,
public userId: string,
Expand All @@ -35,6 +43,30 @@ export class CallFeed extends EventEmitter {
private videoMuted: boolean,
) {
super();

if (this.hasAudioTrack) {
this.initVolumeMeasuring();
}
}

private get hasAudioTrack(): boolean {
return this.stream.getAudioTracks().length > 0;
}

private initVolumeMeasuring(): void {
const AudioContext = window.AudioContext || window.webkitAudioContext;
if (!this.hasAudioTrack || !AudioContext) return;

this.audioContext = new AudioContext();

this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = 512;
this.analyser.smoothingTimeConstant = 0.1;

const mediaStreamAudioSourceNode = this.audioContext.createMediaStreamSource(this.stream);
mediaStreamAudioSourceNode.connect(this.analyser);

this.frequencyBinCount = new Float32Array(this.analyser.frequencyBinCount);
}

/**
Expand Down Expand Up @@ -81,6 +113,12 @@ export class CallFeed extends EventEmitter {
public setNewStream(newStream: MediaStream) {
this.stream = newStream;
this.emit(CallFeedEvent.NewStream, this.stream);

if (this.hasAudioTrack) {
this.initVolumeMeasuring();
} else {
this.measureVolumeActivity(false);
}
}

public setAudioMuted(muted: boolean): void {
Expand All @@ -92,4 +130,36 @@ export class CallFeed extends EventEmitter {
this.videoMuted = muted;
this.emit(CallFeedEvent.MuteStateChanged, this.audioMuted, this.videoMuted);
}

public measureVolumeActivity(enabled: boolean) {
if (enabled) {
if (!this.audioContext || !this.analyser || !this.frequencyBinCount || !this.hasAudioTrack) return;

this.measuringVolumeActivity = true;
this.volumeLooper();
} else {
this.measuringVolumeActivity = false;
this.emit(CallFeedEvent.VolumeChanged, -Infinity);
}
}

private volumeLooper(): void {
if (!this.analyser) return;

setTimeout(() => {
if (!this.measuringVolumeActivity) return;

this.analyser.getFloatFrequencyData(this.frequencyBinCount);

let maxVolume = -Infinity;
for (let i = 0; i < this.frequencyBinCount.length; i++) {
if (this.frequencyBinCount[i] > maxVolume) {
maxVolume = this.frequencyBinCount[i];
}
}

this.emit(CallFeedEvent.VolumeChanged, maxVolume);
this.volumeLooper();
}, POLLING_INTERVAL);
}
}

0 comments on commit 6904f6b

Please sign in to comment.