85 lines
3.4 KiB
JavaScript
85 lines
3.4 KiB
JavaScript
class ProcessorDTMF extends AudioWorkletProcessor {
|
|
constructor() {
|
|
super();
|
|
this.sampleRate = sampleRate;
|
|
this.symbolDuration = 0.03; // 50 ms par symbole
|
|
this.samplesPerSymbol = Math.floor(this.sampleRate * this.symbolDuration);
|
|
this.encodeLowPrio = [];
|
|
this.symbolSamples = [];
|
|
this.lastBlackStep = 0;
|
|
this.port.onmessage = (e) => {
|
|
if (e.data.type === 'encode') {
|
|
this.symbolSamples.push(...this.encodeSymbols(e.data.symbols));
|
|
this.symbolSamples.push(...this.encodeBlack(this.sampleRate * 0.02));
|
|
}
|
|
if (e.data.type === 'encodeLowPrio') {
|
|
this.encodeLowPrio.push(e.data.symbols);
|
|
}
|
|
};
|
|
}
|
|
|
|
dtmfFrequencies = [
|
|
[697, 770, 852, 941], // Fréquences basses
|
|
[1209, 1336, 1477, 1633] // Fréquences hautes
|
|
];
|
|
|
|
encodeSymbols(symbols) {
|
|
const samples = [];
|
|
for (const symbol of symbols) {
|
|
const lf = this.dtmfFrequencies[0][symbol % 4]; // Fréquence basse
|
|
const hf = this.dtmfFrequencies[1][Math.floor(symbol / 4)]; // Fréquence haute
|
|
// console.log(`Symbol: ${symbol}, LF: ${lf} Hz, HF: ${hf} Hz`);
|
|
for (let i = 0; i < this.samplesPerSymbol; i++) {
|
|
const t = i / this.sampleRate;
|
|
const t2 = (this.lastBlackStep + i) / this.sampleRate;
|
|
samples.push(0.5 * Math.sin(2 * Math.PI * lf * t) + 0.5 * Math.sin(2 * Math.PI * hf * t) // Signal DTMF
|
|
+ Math.sin(2 * Math.PI * 150 * t2) * (0.0625 * (Math.sin(2 * Math.PI * 0.5 * t2) + 1))); // Ajouter un signal à 150 Hz pour le "black"
|
|
}
|
|
this.lastBlackStep += this.samplesPerSymbol;
|
|
|
|
// ajouter un silence de 10 ms entre les symboles
|
|
samples.push(...this.encodeBlack(this.sampleRate * 0.01)); // Silence
|
|
}
|
|
return samples;
|
|
}
|
|
|
|
encodeBlack(size) {
|
|
const samples = [];
|
|
|
|
for (let i = 0; i < size; i++) {
|
|
const t = (this.lastBlackStep + i) / this.sampleRate;
|
|
samples.push(Math.sin(2 * Math.PI * 150 * t) * (0.0625 * (Math.sin(2 * Math.PI * 0.5 * t) + 1))); // Signal à 350 Hz pour le "black"
|
|
}
|
|
this.lastBlackStep += size;
|
|
this.lastBlackStep %= this.sampleRate * 2; // Réinitialiser tous les 2 secondes pour éviter les débordements
|
|
|
|
return samples;
|
|
}
|
|
|
|
process(inputs, outputs, parameters) {
|
|
const output = outputs[0]; // output est un tableau de canaux (ex: [Float32Array, ...])
|
|
const channelData = output[0]; // Accéder au premier canal (mono)
|
|
|
|
if (this.symbolSamples.length === 0 && this.encodeLowPrio.length > 0) {
|
|
this.symbolSamples.push(...this.encodeSymbols(this.encodeLowPrio.shift()));
|
|
this.symbolSamples.push(...this.encodeBlack(this.sampleRate * 0.02));
|
|
}
|
|
|
|
if (this.symbolSamples.length === 0) {
|
|
const samples = this.encodeBlack(channelData.length)
|
|
for (let i = 0; i < channelData.length; i++) {
|
|
channelData[i] = samples[i] || 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
for (let i = 0; i < channelData.length; i++) {
|
|
channelData[i] = this.symbolSamples.shift() || 0; // Prendre le prochain échantillon ou 0 si vide
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
registerProcessor('dtmf-processor', ProcessorDTMF);
|