[lib.audio-manager] FREQUENCY or WAVE management (dispatch to callbacks if defined) + [vue.auth.dialog] added draw_freq() + default one + added draw_wave() can toggle between 2 viewers with 'gs.get.toggleDrawStyle()'
This commit is contained in:
parent
2742fd818a
commit
d862215cd8
|
@ -1,6 +1,6 @@
|
||||||
export default class AudioManager{
|
export default class AudioManager{
|
||||||
|
|
||||||
static get BUFFER_SIZE(){ return 8192; }
|
static get BUFFER_SIZE(){ return 4096; }
|
||||||
|
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
|
@ -16,10 +16,15 @@ export default class AudioManager{
|
||||||
/* (3) Initialise input (typically bound from recorder) */
|
/* (3) Initialise input (typically bound from recorder) */
|
||||||
this.input = null;
|
this.input = null;
|
||||||
|
|
||||||
/* (4) Shortcut our output */
|
/* (4) Initialize analyser (from input) + callback */
|
||||||
|
this.analyser = this.ctx.createAnalyser();
|
||||||
|
this.freq_drawer = null;
|
||||||
|
this.wave_drawer = null;
|
||||||
|
|
||||||
|
/* (5) Shortcut our output */
|
||||||
this.output = this.ctx.destination;
|
this.output = this.ctx.destination;
|
||||||
|
|
||||||
/* (5) Connect MASTER gain to output */
|
/* (6) Connect MASTER gain to output */
|
||||||
this.master.connect(this.output);
|
this.master.connect(this.output);
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,12 +176,19 @@ export default class AudioManager{
|
||||||
|
|
||||||
/* (1) Bind audio stream
|
/* (1) Bind audio stream
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
|
/* (1) bind our audio stream to our source */
|
||||||
this.input = this.ctx.createMediaStreamSource(_stream);
|
this.input = this.ctx.createMediaStreamSource(_stream);
|
||||||
|
|
||||||
|
|
||||||
/* (2) By default: link through filters to output
|
/* (2) By default: link through filters to output
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
|
/* (1) Link through filters */
|
||||||
this.linkFilters();
|
this.linkFilters();
|
||||||
|
|
||||||
|
/* (2) Also link to analyser */
|
||||||
|
this.input.connect(this.analyser);
|
||||||
|
|
||||||
|
|
||||||
gs.get.audio_conn = 2; // voice connected
|
gs.get.audio_conn = 2; // voice connected
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -186,18 +198,59 @@ export default class AudioManager{
|
||||||
*
|
*
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
send(_audioprocess){
|
send(_audioprocess){
|
||||||
let buf32 = new Float32Array(AudioManager.BUFFER_SIZE);
|
|
||||||
|
|
||||||
_audioprocess.inputBuffer.copyFromChannel(buf32, 0);
|
/* (1) Manage analyser
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
/* (1) Process only if 'freq_drawer' is set */
|
||||||
|
if( this.freq_drawer instanceof Function ){
|
||||||
|
|
||||||
let buf16 = this.f32toi16(buf32);
|
// 1. Prepare array
|
||||||
|
let freqArray = new Uint8Array(this.analyser.frequencyBinCount);
|
||||||
|
|
||||||
// exit if no connection
|
// 2. Get frequency array
|
||||||
|
this.analyser.getByteFrequencyData(freqArray);
|
||||||
|
|
||||||
|
// 3. Send to callback
|
||||||
|
this.freq_drawer(freqArray);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Process only if 'wave_drawer' is set */
|
||||||
|
else if( this.wave_drawer instanceof Function ){
|
||||||
|
|
||||||
|
// 1. Prepare array
|
||||||
|
let waveArray = new Uint8Array(this.analyser.fftSize);
|
||||||
|
|
||||||
|
// 2. Get wave array
|
||||||
|
this.analyser.getByteTimeDomainData(waveArray);
|
||||||
|
|
||||||
|
// 3. Send to callback
|
||||||
|
this.wave_drawer(waveArray);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* (2) WebSocket send packet
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
/* (1) Exit here if not connected */
|
||||||
if( this.ws === null || this.ws.readyState !== 1 )
|
if( this.ws === null || this.ws.readyState !== 1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* (2) Initialize buffer (Float32Array) */
|
||||||
|
let buf32 = new Float32Array(AudioManager.BUFFER_SIZE);
|
||||||
|
|
||||||
|
/* (3) Extract stream into buffer */
|
||||||
|
_audioprocess.inputBuffer.copyFromChannel(buf32, 0);
|
||||||
|
|
||||||
|
/* (4) Convert for WS connection (Int16Array) */
|
||||||
|
let buf16 = this.f32toi16(buf32);
|
||||||
|
|
||||||
|
/* (5) Send buffer through websocket */
|
||||||
this.ws.send(buf16);
|
this.ws.send(buf16);
|
||||||
|
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
this.dbg.data.packets_sent++;
|
this.dbg.data.packets_sent++;
|
||||||
this.dbg.data.kB_sent += buf16.length * 16. / 8 / 1024;
|
this.dbg.data.kB_sent += buf16.length * 16. / 8 / 1024;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +283,6 @@ export default class AudioManager{
|
||||||
/* (7) Start playing */
|
/* (7) Start playing */
|
||||||
source.start(this.ctx.currentTime);
|
source.start(this.ctx.currentTime);
|
||||||
|
|
||||||
|
|
||||||
this.dbg.data.packets_received++;
|
this.dbg.data.packets_received++;
|
||||||
this.dbg.data.kB_received += _buffer.length * 16. / 8 / 1024;
|
this.dbg.data.kB_received += _buffer.length * 16. / 8 / 1024;
|
||||||
|
|
||||||
|
|
|
@ -225,6 +225,20 @@
|
||||||
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
|
& > canvas{
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
& > div.text-container{
|
& > div.text-container{
|
||||||
|
|
||||||
flex: 1 1 50%;
|
flex: 1 1 50%;
|
||||||
|
@ -234,6 +248,8 @@
|
||||||
|
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
|
|
||||||
|
z-index: 101;
|
||||||
|
|
||||||
& > div.status{
|
& > div.status{
|
||||||
flex: 0 1 100%;
|
flex: 0 1 100%;
|
||||||
|
|
||||||
|
@ -289,8 +305,10 @@
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
z-index: 101;
|
||||||
|
|
||||||
&:hover{
|
&:hover{
|
||||||
background-color: #24262a;
|
background-color: rgba(0,0,0,.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ gs.set('refresh', () => ( document.location = '' ) );
|
||||||
|
|
||||||
/* (6) Connection status */
|
/* (6) Connection status */
|
||||||
gs.set('connection', 1); // null -> normal, 0 -> offline, 1 -> connecting, 2 -> online
|
gs.set('connection', 1); // null -> normal, 0 -> offline, 1 -> connecting, 2 -> online
|
||||||
gs.set('audio_conn', null); // null -> normal, 0 -> connecting, 1 -> listening, 2 -> sharing
|
gs.set('audio_conn', 1); // null -> normal, 0 -> connecting, 1 -> listening, 2 -> sharing
|
||||||
|
|
||||||
/* (7) Ask for permission API */
|
/* (7) Ask for permission API */
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
|
|
|
@ -132,6 +132,8 @@
|
||||||
|
|
||||||
<div class='footer' :data-connected='gs.audio_conn'>
|
<div class='footer' :data-connected='gs.audio_conn'>
|
||||||
|
|
||||||
|
<canvas ref='audio_canvas' width='1000' height='1000'></canvas>
|
||||||
|
|
||||||
<div class='text-container'>
|
<div class='text-container'>
|
||||||
|
|
||||||
<!-- Audio connection status -->
|
<!-- Audio connection status -->
|
||||||
|
@ -159,10 +161,111 @@ export default {
|
||||||
|
|
||||||
name: 'dialog-',
|
name: 'dialog-',
|
||||||
|
|
||||||
data(){ return { gs: gs.get, minipop: false }; },
|
data(){ return {
|
||||||
|
gs: gs.get,
|
||||||
|
minipop: false
|
||||||
|
}; },
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/* show: */
|
|
||||||
|
/* (1) Draw WAVE on canvas from a buffer
|
||||||
|
*
|
||||||
|
* @buffer<Uint8Array> Data buffer
|
||||||
|
*
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
draw_wave(buffer=[]){
|
||||||
|
|
||||||
|
/* (0) Exit if empty buffer */
|
||||||
|
if( !(buffer instanceof Uint8Array) || buffer.length <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* (1) Get <canvas> context + shortcuts */
|
||||||
|
let can = this.$refs.audio_canvas;
|
||||||
|
let ctx = can.getContext('2d', { antialias: false, depth: false });
|
||||||
|
|
||||||
|
/* (2) Adjust dimensions */
|
||||||
|
can.width = buffer.length;
|
||||||
|
can.height = 256;
|
||||||
|
let precision = 1; // bigger -> less precise
|
||||||
|
|
||||||
|
/* (3) Erase previous drawing */
|
||||||
|
ctx.clearRect(0, 0, can.width, can.height);
|
||||||
|
|
||||||
|
/* (4) Begin tracing */
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(0, can.height-buffer[0]);
|
||||||
|
|
||||||
|
/* (5) Trace through each value */
|
||||||
|
for( let i = precision ; i < buffer.length ; i+=precision )
|
||||||
|
ctx.lineTo(i, can.height-buffer[i]);
|
||||||
|
|
||||||
|
/* (6) End tracing */
|
||||||
|
ctx.lineWidth = 7;
|
||||||
|
ctx.strokeStyle = '#44484f';
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* (1) Draw FREQ on canvas from a buffer
|
||||||
|
*
|
||||||
|
* @buffer<Uint8Array> Data buffer
|
||||||
|
*
|
||||||
|
---------------------------------------------------------*/
|
||||||
|
draw_freq(buffer=[]){
|
||||||
|
|
||||||
|
/* (0) Exit if empty buffer */
|
||||||
|
if( !(buffer instanceof Uint8Array) || buffer.length <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* (1) Get <canvas> context + shortcuts */
|
||||||
|
let can = this.$refs.audio_canvas;
|
||||||
|
let ctx = can.getContext('2d', { antialias: false, depth: false });
|
||||||
|
|
||||||
|
/* (2) Adjust dimensions */
|
||||||
|
can.width = buffer.length;
|
||||||
|
can.height = 256;
|
||||||
|
let precision = 5; // bigger -> less precise
|
||||||
|
|
||||||
|
/* (3) Erase previous drawing */
|
||||||
|
ctx.clearRect(0, 0, can.width, can.height);
|
||||||
|
|
||||||
|
/* (4) Begin tracing */
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(0, can.height-128-buffer[0]/2);
|
||||||
|
|
||||||
|
/* (5) Trace through each value */
|
||||||
|
for( let i = precision ; i < buffer.length ; i+=precision )
|
||||||
|
ctx.lineTo(i, can.height-128-buffer[i]/2);
|
||||||
|
|
||||||
|
/* (6) End tracing */
|
||||||
|
ctx.lineWidth = 7;
|
||||||
|
ctx.strokeStyle = '#44484f';
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted(){
|
||||||
|
|
||||||
|
/* (1) By default DRAW FREQUENCY */
|
||||||
|
this.gs.audioManager.freq_drawer = this.draw_freq;
|
||||||
|
|
||||||
|
/* (2) Create toggle method */
|
||||||
|
this.gs.toggleDrawStyle = function(){
|
||||||
|
|
||||||
|
// currently WAVE
|
||||||
|
if( this.gs.audioManager.wave_drawer instanceof Function ){
|
||||||
|
this.gs.audioManager.wave_drawer = null;
|
||||||
|
this.gs.audioManager.freq_drawer = this.draw_freq;
|
||||||
|
}else{
|
||||||
|
this.gs.audioManager.wave_drawer = this.draw_wave;
|
||||||
|
this.gs.audioManager.freq_drawer = null;
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue