angular - Configurarea Tone.js la clic pe buton încă eșuează cu: AudioContext nu a fost permis să pornească
Am un component Angular care are un buton pentru a porni o animație și, în același timp, să redea niște note de fiecare dată când un număr este evidențiat
Configurez sintetizatorul tone.js când este apăsat butonul, vezi escalaPentatonicaToggle, dar încă primesc o eroare despre The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page
De ce primesc acea eroare chiar și atunci când sunetul încearcă să fie redat după un eveniment CLICK? Cum pot să o rezolv?
Am văzut această întrebare similară, dar oferă un scenariu diferit Tone.js - AudioContext nu a fost permis să pornească
Iată logica componentului
import { Component } from '@angular/core';
import { ElementoPentatonica, EscalaPentatonica, NotasEscalaPentatonica } from '../../models/EscalaPentatonica';
import { CommonModule } from '@angular/common';
import { ElementoPentatonicaComponent } from '../elemento-pentatonica/elemento-pentatonica.component';
import * as Tone from 'tone';
@Component({
selector: 'app-escala-pentatonica',
standalone: true,
imports: [CommonModule, ElementoPentatonicaComponent],
templateUrl: './escala-pentatonica.component.html',
styleUrl: './escala-pentatonica.component.css'
})
export class EscalaPentatonicaComponent {
escala: EscalaPentatonica;
highlightedIndex: number = 0;
timer: any;
lapse: number = 600;
running: boolean = false;
soundEnabled: boolean = true;
sonido = "LA";
start = 1;
lineasFlat: ElementoPentatonica[] = [];
synth: Tone.Synth | null = null;
constructor() {
this.escala = new EscalaPentatonica(this.start, NotasEscalaPentatonica.SI_MAYOR, this.sonido);
this.lineasFlat = this.escala.lineas.flat();
}
onSelectionChange(event: Event) {
this.stopAnimation();
this.start = Number((event.target as HTMLSelectElement).value);
this.escala = new EscalaPentatonica(this.start, NotasEscalaPentatonica.SI_MAYOR, this.sonido);
}
ngOnInit() {
}
async escalaPentatonicaToggle() {
await Tone.start();
if (!this.running) {
await this.startAnimation();
} else {
this.stopAnimation();
}
this.running = !this.running;
}
async startAnimation() {
this.synth = new Tone.Synth().toDestination();
this.highlightedIndex = 0;
this.startTimer();
}
stopAnimation() {
if (this.timer) {
clearInterval(this.timer);
}
if (this.synth) {
this.synth.dispose();
this.synth = null;
}
}
ngOnDestroy() {
this.stopAnimation();
}
startTimer() {
this.timer = setInterval(() => {
this.highlightedIndex = (this.highlightedIndex + 1) % this.lineasFlat.length;
this.playSound(this.highlightedIndex);
}, this.lapse);
}
getIndex(i: number, j: number): number {
let index = 0;
for (let x = 0; x < i; x++) {
index += this.escala.lineas[x].length;
}
return index + j;
}
playSound(index: number) {
let note = this.escala.notas[this.lineasFlat[index].numero - this.escala.start];
if (this.synth) {
console.log('Playing note:', note);
this.synth.triggerAttackRelease(note, '2s');
}
}
}
și aici este html-ul
<div class="escala-container">
<select #escalaSelect (change)="onSelectionChange($event)">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<button class="nextButton" (click)="escalaPentatonicaToggle()">
{{ running ? 'DETENER' : 'INICIAR' }}
</button>
<div *ngFor="let linea of escala.lineas; let i = index" class="linea" [style.margin-left.px]="(4 - i) * 20">
<app-elemento-pentatonica *ngFor="let elemento of linea; let j = index" [numero]="elemento.numero"
[sonido]="elemento.sonido" [highlight]="highlightedIndex === getIndex(i, j)">
</app-elemento-pentatonica>
</div>
</div>
Răspuns #1
Problem rezolvat, motiv „Fila a fost dezactivată sonor”. Da, este jenant ;-)
De asemenea, mesajele din consolă sunt AVERTISMENTE, nu erori, și sunetul se redă fără probleme.
