una sonidos sonido senoidal poner para online ondas onda graficar funciones dibujar detener como codigo agregar java audio javasound

sonidos - Ruido en el fondo al generar onda sinusoidal en Java



graficar funciones en processing (2)

Supongo que está llamando a este código varias veces para reproducir un sonido largo.

¿Existe la posibilidad de que la ola que está generando no llegue a completar un período completo antes de que se escriba?

Si la onda se "corta" antes de que complete un período completo y luego la siguiente onda se escriba en la salida, seguramente escuchará algo extraño y supongo que puede ser lo que está causando el zumbido.

Por ejemplo:

/-------/ /-------/ /-------/ -----/ / -----/ / -----/ / / / / /----- /----- /-----

Observe la desconexión entre las partes de esta ola. Eso podría estar causando el zumbido.

Obtengo una ligera distorsión (suena como zumbido) en el fondo cuando ejecuto el siguiente código. Debido a su naturaleza sutil, hace creer que hay algún tipo de alias con el byte de fundición.

AudioFormat = PCM_SIGNED 44100.0 Hz, 16 bit, estéreo, 4 bytes / cuadro, big-endian

Nota : el código asume (por ahora) que los datos están en big endian.

public static void playFreq(AudioFormat audioFormat, double frequency, SourceDataLine sourceDataLine) { System.out.println(audioFormat); double sampleRate = audioFormat.getSampleRate(); int sampleSizeInBytes = audioFormat.getSampleSizeInBits() / 8; int channels = audioFormat.getChannels(); byte audioBuffer[] = new byte[(int)Math.pow(2.0, 19.0) * channels * sampleSizeInBytes]; for ( int i = 0; i < audioBuffer.length; i+=sampleSizeInBytes*channels ) { int wave = (int) (127.0 * Math.sin( 2.0 * Math.PI * frequency * i / (sampleRate * sampleSizeInBytes * channels) ) ); //wave = (wave > 0 ? 127 : -127); if ( channels == 1 ) { if ( sampleSizeInBytes == 1 ) { audioBuffer[i] = (byte) (wave); } else if ( sampleSizeInBytes == 2 ) { audioBuffer[i] = (byte) (wave); audioBuffer[i+1] = (byte)(wave >>> 8); } } else if ( channels == 2 ) { if ( sampleSizeInBytes == 1 ) { audioBuffer[i] = (byte) (wave); audioBuffer[i+1] = (byte) (wave); } else if ( sampleSizeInBytes == 2 ) { audioBuffer[i] = (byte) (wave); audioBuffer[i+1] = (byte)(wave >>> 8); audioBuffer[i+2] = (byte) (wave); audioBuffer[i+3] = (byte)(wave >>> 8); } } } sourceDataLine.write(audioBuffer, 0, audioBuffer.length); }


Sus comentarios dicen que el código asume big-endian.

Técnicamente estás produciendo en little-endian, sin embargo, no parece importar porque a través de un capricho de la suerte tu byte más significativo es siempre 0.

EDITAR: para explicar eso aún más: cuando su valor está en su valor máximo de 127, debe escribir (0x00, 0x7f), pero la salida real de su código es (0x7f, 0x00) que es 32512. Esto pasa a estar cerca el valor máximo correcto de 16 bits de 32767, pero con los 8 bits inferiores todos son cero. Sería mejor usar siempre 32767 como el valor máximo, y luego descartar los 8 bits inferiores si es necesario.

Esto significa que, aunque está produciendo datos de 16 bits, la resolución efectiva es de solo 8 bits. Esto parece explicar la falta de calidad de sonido.

He creado una versión de tu código que simplemente descarga los datos sin procesar a un archivo y no puede ver nada incorrecto con el cambio de bit. No hay cambios inesperados de signo o bits faltantes, pero hay un zumbido consistente con la calidad de muestra de 8 bits.

Además, por lo que vale la pena, tus cálculos serán más fáciles si calculas la ecuación de onda en función de los conteos de muestras, y luego te preocupas por los desfases de bytes por separado:

int samples = 2 << 19; byte audioBuffer[] = new byte[samples * channels * sampleSizeInBytes]; for ( int i = 0, j = 0; i < samples; ++i ) { int wave = (int)(32767.0 * Math.sin(2.0 * Math.PI * frequency * i / sampleRate)); byte msb = (byte)(wave >>> 8); byte lsb = (byte) wave; for (int c = 0; c < channels; ++c) { audioBuffer[j++] = msb; if (sampleSizeInBytes > 1) { audioBuffer[j++] = lsb; } } }