add opus server-side integration
This commit is contained in:
parent
26440d4e24
commit
a6f2b6b31a
@ -1,5 +1,5 @@
|
|||||||
from csdr.chain import Chain
|
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
|
from pycsdr.types import Format
|
||||||
|
|
||||||
|
|
||||||
@ -27,6 +27,8 @@ class ClientAudioChain(Chain):
|
|||||||
workers += [converter]
|
workers += [converter]
|
||||||
if compression == "adpcm":
|
if compression == "adpcm":
|
||||||
workers += [AdpcmEncoder(sync=True)]
|
workers += [AdpcmEncoder(sync=True)]
|
||||||
|
elif compression == "opus":
|
||||||
|
workers += [OpusEncoder()]
|
||||||
super().__init__(workers)
|
super().__init__(workers)
|
||||||
|
|
||||||
def _buildConverter(self):
|
def _buildConverter(self):
|
||||||
@ -63,10 +65,18 @@ class ClientAudioChain(Chain):
|
|||||||
self._updateConverter()
|
self._updateConverter()
|
||||||
|
|
||||||
def setAudioCompression(self, compression: str) -> None:
|
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":
|
if compression == "adpcm":
|
||||||
|
newEncoder = AdpcmEncoder(sync=True)
|
||||||
|
elif compression == "opus":
|
||||||
|
newEncoder = OpusEncoder()
|
||||||
|
|
||||||
|
if newEncoder:
|
||||||
if index < 0:
|
if index < 0:
|
||||||
self.append(AdpcmEncoder(sync=True))
|
self.append(newEncoder)
|
||||||
|
else:
|
||||||
|
self.replace(index, newEncoder)
|
||||||
else:
|
else:
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
self.remove(index)
|
self.remove(index)
|
||||||
|
@ -21,7 +21,11 @@ function AudioEngine(maxBufferLength, audioReporter) {
|
|||||||
me._start();
|
me._start();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.audioCodec = new ImaAdpcmCodec();
|
this.audioCodecs = {
|
||||||
|
"adpcm": new ImaAdpcmCodec(),
|
||||||
|
"opus": new OpusCodec(this.audioContext)
|
||||||
|
};
|
||||||
|
|
||||||
this.compression = 'none';
|
this.compression = 'none';
|
||||||
|
|
||||||
this.setupResampling();
|
this.setupResampling();
|
||||||
@ -277,25 +281,31 @@ AudioEngine.prototype.getSampleRate = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AudioEngine.prototype.processAudio = function(data, resampler) {
|
AudioEngine.prototype.processAudio = function(data, resampler) {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
if (!this.audioNode) return;
|
if (!this.audioNode) return;
|
||||||
this.audioBytes.add(data.byteLength);
|
this.audioBytes.add(data.byteLength);
|
||||||
var buffer;
|
|
||||||
if (this.compression === "adpcm") {
|
var audioDataCallback = function(buffer) {
|
||||||
//resampling & ADPCM
|
|
||||||
buffer = this.audioCodec.decodeWithSync(new Uint8Array(data));
|
|
||||||
} else {
|
|
||||||
buffer = new Int16Array(data);
|
|
||||||
}
|
|
||||||
buffer = resampler.process(buffer);
|
buffer = resampler.process(buffer);
|
||||||
if (this.audioNode.port) {
|
if (me.audioNode.port) {
|
||||||
// AudioWorklets supported
|
// AudioWorklets supported
|
||||||
this.audioNode.port.postMessage(buffer);
|
me.audioNode.port.postMessage(buffer);
|
||||||
} else {
|
} else {
|
||||||
// silently drop excess samples
|
// silently drop excess samples
|
||||||
if (this.getBuffersize() + buffer.length <= this.maxBufferSize) {
|
if (this.getBuffersize() + buffer.length <= this.maxBufferSize) {
|
||||||
this.audioBuffers.push(buffer);
|
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) {
|
AudioEngine.prototype.pushAudio = function(data) {
|
||||||
@ -357,7 +367,7 @@ ImaAdpcmCodec.prototype.decode = function(data) {
|
|||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImaAdpcmCodec.prototype.decodeWithSync = function(data) {
|
ImaAdpcmCodec.prototype.decodeAsync = function(data, callback) {
|
||||||
var output = new Int16Array(data.length * 2);
|
var output = new Int16Array(data.length * 2);
|
||||||
var index = this.skip;
|
var index = this.skip;
|
||||||
var oi = 0;
|
var oi = 0;
|
||||||
@ -391,7 +401,7 @@ ImaAdpcmCodec.prototype.decodeWithSync = function(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.skip = index - data.length;
|
this.skip = index - data.length;
|
||||||
return output.slice(0, oi);
|
callback(output.slice(0, oi));
|
||||||
};
|
};
|
||||||
|
|
||||||
ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
|
ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
|
||||||
@ -412,6 +422,14 @@ ImaAdpcmCodec.prototype.decodeNibble = function(nibble) {
|
|||||||
return this.predictor;
|
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) {
|
function Interpolator(factor) {
|
||||||
this.factor = factor;
|
this.factor = factor;
|
||||||
this.lowpass = new Lowpass(factor)
|
this.lowpass = new Lowpass(factor)
|
||||||
|
@ -754,7 +754,7 @@ function on_ws_recv(evt) {
|
|||||||
if ('audio_compression' in config) {
|
if ('audio_compression' in config) {
|
||||||
var audio_compression = config['audio_compression'];
|
var audio_compression = config['audio_compression'];
|
||||||
audioEngine.setCompression(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) {
|
if ('fft_compression' in config) {
|
||||||
fft_compression = config['fft_compression'];
|
fft_compression = config['fft_compression'];
|
||||||
|
@ -132,6 +132,7 @@ class GeneralSettingsController(SettingsFormController):
|
|||||||
"Audio compression",
|
"Audio compression",
|
||||||
options=[
|
options=[
|
||||||
Option("adpcm", "ADPCM"),
|
Option("adpcm", "ADPCM"),
|
||||||
|
Option("opus", "OPUS"),
|
||||||
Option("none", "None"),
|
Option("none", "None"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user