Generador de tono aleatorio con API de audio web -- javascript campo con random campo con html5 campo con audio camp codereview Relacionados El problema

Random tone generator using Web Audio API


5
vote

problema

Español

Este es un generador de audio de frecuencia aleatorio realizado con la API de audio web de Mozilla. El objetivo final es un entrenador de frecuencia de audio: el sitio web juega una frecuencia de audio y el usuario intenta adivinar qué frecuencia es. Las frecuencias se limitarán a las que se encuentran en los ecualizadores gráficos de 31 bandas, e incluiré múltiples dificultades.

Este es mi primer paso: el generador para la dificultad 'Fácil' (4 frecuencias).

  // create web audio api context var audioCtx = new AudioContext();  // create oscillator (tone) and gain (volume) node var tone = audioCtx.createOscillator(); var volume = audioCtx.createGain();  // create array of frequency values var frequencies = ["100", "400", "1600", "6300"]; // pick a random frequency var frequency = frequencies[Math.floor(Math.random() * frequencies.length)];  // set oscillator type (sine, square, sawtooth or triangle) tone.type = 'sine'; // set oscillator frequency in Hz tone.frequency.value = frequency; // set gain volume (above 1 will clip) volume.gain.value = 0.5;  // set tone destination to go through volume tone.connect(volume); // set volume destination to output volume.connect(audioCtx.destination);  // start oscillator x seconds after timestamp tone.start(1); // stop oscillator x seconds after timestamp tone.stop(4);   

No me importa la comenta excesiva, solo acaba de comenzar a usar JavaScript y no confiemos en mí mismo para recordar lo que cada línea de código lo hace después de unos días.

Original en ingles

This is a random frequency audio generator made with the Web Audio API by Mozilla. The end-goal is an audio frequency trainer: the website plays an audio frequency and the user tries to guess which frequency it is. The frequencies will be limited to those found on 31 band graphical equalisers, and I'll include multiple difficulties.

This is my first step: the generator for the 'easy' difficulty (4 frequencies).

// create web audio api context var audioCtx = new AudioContext();  // create oscillator (tone) and gain (volume) node var tone = audioCtx.createOscillator(); var volume = audioCtx.createGain();  // create array of frequency values var frequencies = ["100", "400", "1600", "6300"]; // pick a random frequency var frequency = frequencies[Math.floor(Math.random() * frequencies.length)];  // set oscillator type (sine, square, sawtooth or triangle) tone.type = 'sine'; // set oscillator frequency in Hz tone.frequency.value = frequency; // set gain volume (above 1 will clip) volume.gain.value = 0.5;  // set tone destination to go through volume tone.connect(volume); // set volume destination to output volume.connect(audioCtx.destination);  // start oscillator x seconds after timestamp tone.start(1); // stop oscillator x seconds after timestamp tone.stop(4); 

Don't mind the excessive commentation, I've only just started using JavaScript and don't trust myself to remember what every line of code does after a few days.

           
     
     

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Código reutilizable

El código no es muy flexible, y las frecuencias son un poco arbitrarias y que abarcan una gran cantidad de 6 octavas.

Puede encapsular el código en una función que crea un objeto que usa para reproducir el tono aleatorio según sea necesario, lo que le permite agregar características como necesita.

Nota amistosa

Considere el uso de notas musicales estándar en lugar de frecuencias aleatorias.

Para obtener la frecuencia de una nota que usa la expresión

  freq = 2 ** (note / 12) * 440;   

Donde la nota es la cantidad de semi tonos de A4 440Hz. Así que para encontrar C4, que es 3 notas hasta 2 ** (3 / 12) * 440;

Para obtener la nota más cercana a una frecuencia que usa

  note = Math.round(Math.log2(freq / 440) * 12);   

Ejemplo básico

El ejemplo crea ese objeto randomNotes y reproduce notas musicales en lugar de tonos aleatorios.

  const randomNotes= (() => {          /* Create the objects needed to play a tone */     const audio = new AudioContext();     const volume = audio.createGain();      volume.gain.value = 0.5;     volume.connect(audio.destination);          /* Function to calculate frequency of a note starting at A4 and stepping semi tones*/         const freq = note => 2 ** (note / 12) * 440; // 440 is the frequency of A4     const randomNote = () => notes[Math.random() * notes.length | 0]; // the bitwise Or does the same as Math.floor     const notes = [-25, -2, 22, 46]; // Close to your 100, 400, 1600 and 6300      /* Create and return the object that is the randomNote */         return {         play(startIn = 1, playFor = 4) { // startIn and playFor is time in seconds             const now = audio.currentTime;             const oscillator = audio.createOscillator();             oscillator.type = "sine";             oscillator.connect(volume);                         oscillator.frequency.value = freq(randomNote());             oscillator.start(now + startIn);               oscillator.stop(now + startIn + playFor);           }     }; })();  

Luego, para jugar una nota aleatoria, solo llame

  randomNotes.play();   

o jugando dos tonos

  randomNotes.play(); setTimeout(randomNotes.play, 6000);   

o tonos superpuestos

  randomNotes.play(); setTimeout(randomNotes.play, 3000); // starts half way through the first   

Reutilizando el código

Las ventajas de usar este Approch es que se vuelve muy fácil extender la funcionalidad. Diga que desea agregar control de volumen, o poder agregar notas a la lista aleatoria, simplemente agregue un setter al objeto devuelto,

  // from above snippet /* Create and return the object that is the randomNote */     return {     set volume(value) { volume.gain.value = value },     set note(value) { notes.push(value) }      // continue on from above snippet     play(startIn = 1, playFor = 4) { ...   

Puede configurar el volumen de una manera más abstracta y agregar notas al conjunto aleatorio con facilidad.

  freq = 2 ** (note / 12) * 440; 0  

Más sonido.

Notará que hay un nuevo oscilador creado cada vez, y que la hora actual del contexto de audio continúa marque. Es mucho más eficiente crear un oscilador y cambiar su frecuencia según sea necesario y usar temporizadores para cambiar el volumen para comenzar a detener el sonido. Un oscilador no puede reiniciarse después de haber sido detenido.

Pero esto no es lo mejor, ya sea, ya que el contexto de audio puede masticar un poco de energía y CPU, incluso cuando no se reproducen el sonido (en algún hardware de audio). Lo ideal es que suspenda el contexto de audio y lo reanude según sea necesario, junto con el uso del control de ganancia para iniciar y detener el oscilador, ya que el contexto de audio a veces puede ser un poco lento al suspender.

Personalmente, crearía este tipo de cosas con un búfer de audio y simplemente escribiría la forma de onda directamente al búfer y luego jugarlo.

 

Reusable code

You code is not very flexible, and the frequencies somewhat arbitrary and spanning a large 6 octaves.

You can encapsulate the code in a function that creates an object you use to play the random tone as needed, allowing you to add features as you need.

Note friendly

Consider using standard musical notes rather than random frequencies.

To get the frequency of a note you use the expression

freq = 2 ** (note / 12) * 440; 

where note is the number of semi tones from A4 440Hz. So to find C4 which is 3 notes up 2 ** (3 / 12) * 440;

To get the closest note to a frequency you use

note = Math.round(Math.log2(freq / 440) * 12); 

Basic example

The example creates that object randomNotes and plays musical notes rather than random tones.

const randomNotes= (() => {          /* Create the objects needed to play a tone */     const audio = new AudioContext();     const volume = audio.createGain();      volume.gain.value = 0.5;     volume.connect(audio.destination);          /* Function to calculate frequency of a note starting at A4 and stepping semi tones*/         const freq = note => 2 ** (note / 12) * 440; // 440 is the frequency of A4     const randomNote = () => notes[Math.random() * notes.length | 0]; // the bitwise Or does the same as Math.floor     const notes = [-25, -2, 22, 46]; // Close to your 100, 400, 1600 and 6300      /* Create and return the object that is the randomNote */         return {         play(startIn = 1, playFor = 4) { // startIn and playFor is time in seconds             const now = audio.currentTime;             const oscillator = audio.createOscillator();             oscillator.type = "sine";             oscillator.connect(volume);                         oscillator.frequency.value = freq(randomNote());             oscillator.start(now + startIn);               oscillator.stop(now + startIn + playFor);           }     }; })();

Then to play a random note just call

randomNotes.play(); 

or playing two tones

randomNotes.play(); setTimeout(randomNotes.play, 6000); 

or overlapping tones

randomNotes.play(); setTimeout(randomNotes.play, 3000); // starts half way through the first 

Reusing the code

The Advantages of using this approch is that it becomes very easy to extend the functionality. Say you want to add volume control, or be able to add notes to the random list, just add a setter to the object returned,

// from above snippet /* Create and return the object that is the randomNote */     return {     set volume(value) { volume.gain.value = value },     set note(value) { notes.push(value) }      // continue on from above snippet     play(startIn = 1, playFor = 4) { ... 

You can then set the volume in a more abstract way and add notes to the random set with ease.

randomNotes.note = 12; // Add note A5 to the random set randomNotes.volume = 0.8; // Increase the volume 

More sound.

You will notice that there is a new oscillator created each time, and that the audio context's current time continues to tick. It is much more efficient to create one oscillator and change its frequency as needed and using timers to change the volume to start stop the sound. An oscillator can not restart after it has been stopped.

But this is not the best either as the audio context can chew some serious power and CPU even when not playing sound (On some audio hardware). Ideally you suspend the audio context and resume it as needed, in conjunction to using the gain control to start and stop the oscillator, as the audio context can sometimes be a little slow when suspending .

Personally I would create this type of thing using an audio buffer and just write the waveform directly to the buffer then play it.

 
 
   
   
2
 
vote

Dijiste ...

No me importa la comenta excesiva, solo acaba de comenzar a usar JavaScript y no confiemos en mí mismo para recordar lo que cada línea de código lo hace después de unos días.

Pero comentando cada línea es un mal hábito para que se forme un principiante. Algunos de los comentarios son realmente muy redundantes y molestos:

  freq = 2 ** (note / 12) * 440; 1  

Los comentarios deben ser utilizados con juiciosidad. Creo que esta cantidad de comentarios sería suficiente, incluso para un principiante:

  freq = 2 ** (note / 12) * 440; 2  

Para mayor claridad, he cambiado de nombre freq = 2 ** (note / 12) * 440; 3 freq = 2 ** (note / 12) * 440; 4 (Para que se borra que actúa como una fuente de sonido), y 99887766555443315 freq = 2 ** (note / 12) * 440; 6 (porque ese nodo es un componente; 99887766555443317 no tiene sentido).

 

You saidxe2x80xa6

Don't mind the excessive commentation, I've only just started using JavaScript and don't trust myself to remember what every line of code does after a few days.

But commenting every line is a bad habit for a beginner to form. Some of the comments are really very redundant and annoying:

// create web audio api context var audioCtx = new AudioContext();  // create oscillator (tone) and gain (volume) node var tone = audioCtx.createOscillator(); var volume = audioCtx.createGain(); 

Comments should be used judiciously. I think that this amount of commenting would be plenty, even for a beginner:

// Pick one of these frequencies (in Hz) randomly var frequencies = ["100", "400", "1600", "6300"]; var frequency = frequencies[(Math.random() * frequencies.length) | 0];  var audioCtx = new AudioContext();  var toneGen = audioCtx.createOscillator(); toneGen.type = 'sine';       // could be sine, square, sawtooth or triangle toneGen.frequency.value = frequency;  var amplifier = audioCtx.createGain(); amplifier.gain.value = 0.5;  // setting gain above 1 would clip  // Connect nodes: toneGen -> amplifier -> output toneGen.connect(amplifier); amplifier.connect(audioCtx.destination);  // Start playing tone at 1 sec, stop at 2 sec toneGen.start(1); toneGen.stop(2);

For clarity, I've renamed tone xe2x86x92 toneGen (to make it clear that it acts as a sound source), and volume xe2x86x92 amplifier (because that node is a component; tone.connect(volume) makes no sense).

 
 
   
   

Relacionados problema

5  Selector y reproductor de MP3 aleatorio  ( Random mp3 selector and player ) 
Entonces, soy un glotón para el castigo, o no tengo vida, pero yo escribió un script para responder una pregunta sobre Preguntar en preguntar Ubuntu como sol...

4  Optimización de SSE para remuestreo de audio [cerrado]  ( Sse optimisation for audio resampling ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

1  Pasando objetos atómicamente a través de hilos sin cerraduras o carreras de datos para la sincronización de audio  ( Passing objects atomically across threads without locks or data races for audio ) 
Estoy aprendiendo sobre una de las partes más difíciles del desarrollo de audio: la sincronización entre el hilo de audio y el hilo GUI. Por la discusión aquí...

1  Un javafx para generar sonido de pitidos en Windows a través de JNI  ( A javafx for generating beeping sound on windows via jni ) 
Este es mi programa de práctica: un cuadro de diálogo simple que usa el cual un usuario puede especificar una frecuencia de una señal de audio sinusal y repro...

2  Commandline StreamFormatter  ( Commandline streamformattester ) 
Uso del libro de Chris Adamson Aprendizaje de audio Core Me estoy familiarizando con el audio básico para Mac / iOS. Los ejemplos de código son 100% objetiv...

6  Reproductor de audio en Angular 2  ( Audio player in angular 2 ) 
Acabo de construir un reproductor de audio en Angular 2 usando un componente de reproductor y un servicio de jugador. Todo está funcionando bien, solo siento ...

5  HTML y JQUERY AUDIO PLAYER  ( Html and jquery audio player ) 
Tuve una tarea para crear un reproductor de audio simple. Hasta ahora logré hacer funcionalidades y todo lo que se necesita. Otra parte de la misma tarea era ...

1  Verificación de forma de JS  ( Js form verification ) 
Tengo tres checboxes en mi forma. Tengo que comprobar cuál se comprueba y comienza la acción. ¿Qué piensas? ¿Es esta la forma más fácil de hacerlo? casilla...

3  Clase de Audiocontroller para administrar audio en Juegos de Unity  ( Audiocontroller class for managing audio in unity games ) 
Estoy buscando una crítica de este sistema de gestión de audio que escribí para los juegos de unidad. Referencias a un archivo JSON para activar los clips por...

7  Implementación de algoritmo de detección de vencimiento  ( Beat detection algorithm implementation ) 
¿Cuál es la calidad del código que he escrito? ¿Es fácil leer o es un pedazo de código de baja calidad? Además, ¿hay alguna forma en que pueda mejorar el algo...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos