add opus server-side integration

This commit is contained in:
Jakob Ketterl 2022-06-18 20:23:50 +02:00
parent 26440d4e24
commit a6f2b6b31a
4 changed files with 51 additions and 22 deletions

View File

@ -1,5 +1,5 @@
from csdr.chain import Chain
from pycsdr.modules import AudioResampler, Convert, AdpcmEncoder, Limit
from pycsdr.modules import AudioResampler, Convert, AdpcmEncoder, OpusEncoder, Limit
from pycsdr.types import Format
@ -27,6 +27,8 @@ class ClientAudioChain(Chain):
workers += [converter]
if compression == "adpcm":
workers += [AdpcmEncoder(sync=True)]
elif compression == "opus":
workers += [OpusEncoder()]
super().__init__(workers)
def _buildConverter(self):
@ -63,10 +65,18 @@ class ClientAudioChain(Chain):
self._updateConverter()
def setAudioCompression(self, compression: str) -> None:
index = self.indexOf(lambda x: isinstance(x, AdpcmEncoder))
index = self.indexOf(lambda x: isinstance(x, AdpcmEncoder) or isinstance(x, OpusEncoder))
newEncoder = None
if compression == "adpcm":
newEncoder = AdpcmEncoder(sync=True)
elif compression == "opus":
newEncoder = OpusEncoder()
if newEncoder:
if index < 0:
self.append(AdpcmEncoder(sync=True))
self.append(newEncoder)
else:
self.replace(index, newEncoder)
else:
if index >= 0:
self.remove(index)

View File

@ -21,7 +21,11 @@ function AudioEngine(maxBufferLength, audioReporter) {
me._start();
}
this.audioCodec = new ImaAdpcmCodec();
this.audioCodecs = {
"adpcm": new ImaAdpcmCodec(),
"opus": new OpusCodec(this.audioContext)
};
this.compression = 'none';
this.setupResampling();
@ -277,25 +281,31 @@ AudioEngine.prototype.getSampleRate = function() {
};
AudioEngine.prototype.processAudio = function(data, resampler) {
var me = this;
if (!this.audioNode) return;
this.audioBytes.add(data.byteLength);
var buffer;
if (this.compression === "adpcm") {
//resampling & ADPCM
buffer = this.audioCodec.decodeWithSync(new Uint8Array(data));
} else {
buffer = new Int16Array(data);
}
buffer = resampler.process(buffer);
if (this.audioNode.port) {
// AudioWorklets supported
this.audioNode.port.postMessage(buffer);
} else {
// silently drop excess samples
if (this.getBuffersize() + buffer.length <= this.maxBufferSize) {
this.audioBuffers.push(buffer);
var audioDataCallback = function(buffer) {
buffer = resampler.process(buffer);
if (me.audioNode.port) {
// AudioWorklets supported
me.audioNode.port.postMessage(buffer);
} else {
// silently drop excess samples
if (this.getBuffersize() + buffer.length <= this.maxBufferSize) {
this.audioBuffers.push(buffer);
}
}
}
if (this.compression !== "none") {
//resampling & ADPCM
this.audioCodecs[this.compression].decodeAsync(new Uint8Array(data), audioDataCallback);
} else {
audioDataCallback(new Int16Array(data))
}
}
AudioEngine.prototype.pushAudio = function(data) {
@ -357,7 +367,7 @@ ImaAdpcmCodec.prototype.decode = function(data) {
return output;
};
ImaAdpcmCodec.prototype.decodeWithSync = function(data) {
ImaAdpcmCodec.prototype.decodeAsync = function(data, callback) {
var output = new Int16Array(data.length * 2);
var index = this.skip;
var oi = 0;
@ -391,7 +401,7 @@ ImaAdpcmCodec.prototype.decodeWithSync = function(data) {
}
}
this.skip = index - data.length;
return output.slice(0, oi);
callback(output.slice(0, oi));
};
ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
@ -412,6 +422,14 @@ ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
return this.predictor;
};
function OpusCodec(context) {
this.context = context;
}
OpusCodec.prototype.decodeAsync = function(data, callback) {
this.context.decodeAudioData(new ArrayBuffer(data)).then(callback);
};
function Interpolator(factor) {
this.factor = factor;
this.lowpass = new Lowpass(factor)

View File

@ -754,7 +754,7 @@ function on_ws_recv(evt) {
if ('audio_compression' in config) {
var audio_compression = config['audio_compression'];
audioEngine.setCompression(audio_compression);
divlog("Audio stream is " + ((audio_compression === "adpcm") ? "compressed" : "uncompressed") + ".");
divlog("Audio stream is " + ((audio_compression !== "none") ? "compressed" : "uncompressed") + ".");
}
if ('fft_compression' in config) {
fft_compression = config['fft_compression'];

View File

@ -132,6 +132,7 @@ class GeneralSettingsController(SettingsFormController):
"Audio compression",
options=[
Option("adpcm", "ADPCM"),
Option("opus", "OPUS"),
Option("none", "None"),
],
),