2009-04-11 18 views
5

Obtengo una leve 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.Ruido en el fondo al generar onda sinusoidal en Java

AudioFormat = PCM_SIGNED 44100,0 Hz, 16 bits, estéreo, 4 bytes/marco, bigEndian

Nota: código se supone (por ahora) de 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); 
} 

Respuesta

7

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

Técnicamente eres en realidad salida en ascendente hacia la izquierda, sin embargo, no parece importar porque a través de una peculiaridad de su suerte byte más significativo es siempre 0.

EDIT: para explicar que 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 está cerca del valor correcto 16 bit máximo 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 su código que solo 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 su matemática será más fácil si se calcula la ecuación de onda basado en cuentas de la muestra, y luego preocuparse por desplazamientos 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; 
     } 
    } 
} 
+0

¡Ah! Vea el error ahora, después de corregir la parte de amplitud, el error se hizo evidente, pero su código también es más eficiente. ¡Gracias! – yxk

+0

¡Análisis bien hecho! –

2

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

¿Existe la posibilidad de que la onda 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 escribe en la salida, seguramente escuchará algo extraño y supongo que puede ser lo que está causando el zumbido.

Por ejemplo:

 /-------\    /-------\    /-------\ 
    -----/   \  -----/   \  -----/   \ 
        \      \      \ 
        \-----     \-----     \----- 

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

+0

Sí, no es esa cuestión porque el búfer es lo suficientemente grande como para que el sonido atraviese muchos ciclos. No cuenta para el clic, pero no para el zumbido constante. – yxk

+0

esta no es la respuesta correcta: el código genera claramente muchas muestras y no hay truncamiento al final de cada ciclo – Alnitak

+0

y probé el código para verificar; es un error de cuantificación inadvertido de 8 bits que está causando el zumbido. – Alnitak

Cuestiones relacionadas