Saltar al contenido

¿Cómo puedo detectar si un archivo WAV tiene un encabezado de 44 o 46 bytes?

Si te encuentras con algo que no entiendes puedes comentarlo y trataremos de ayudarte tan rápido como podamos.

Solución:

Debería comprobar todos los datos del encabezado para ver cuáles son los tamaños reales. Los archivos Broadcast Wave Format contendrán un subgrupo de extensión aún mayor. Los archivos WAV y AIFF de Pro Tools tienen incluso más fragmentos de extensión que no están documentados, así como datos después del audio. Si desea estar seguro de dónde comienzan y terminan los datos de muestra, debe buscar realmente el fragmento de datos (‘datos’ para archivos WAV y ‘SSND’ para AIFF).

Como revisión, todos los subgrupos WAV se ajustan al siguiente formato:

Subchunk Descriptor (4 bytes)
    Subchunk Size (4 byte integer, little endian)
    Subchunk Data (size is Subchunk Size)

Esto es muy fácil de procesar. Todo lo que necesitas hacer es leer el descriptor, si no es el que estás buscando, lee el tamaño de los datos y pasa al siguiente. Una simple rutina de Java para hacer eso se vería así:

//
// Quick note for people who don't know Java well:
// 'in.read(...)' returns -1 when the stream reaches
// the end of the file, so 'if (in.read(...) < 0)'
// is checking for the end of file.
//
public static void printWaveDescriptors(File file)
        throws IOException 
    try (FileInputStream in = new FileInputStream(file)) 
        byte[] bytes = new byte[4];

        // Read first 4 bytes.
        // (Should be RIFF descriptor.)
        if (in.read(bytes) < 0) 
            return;
        

        printDescriptor(bytes);

        // First subchunk will always be at byte 12.
        // (There is no other dependable constant.)
        in.skip(8);

        for (;;) 
            // Read each chunk descriptor.
            if (in.read(bytes) < 0) 
                break;
            

            printDescriptor(bytes);

            // Read chunk length.
            if (in.read(bytes) < 0) 
                break;
            

            // Skip the length of this chunk.
            // Next bytes should be another descriptor or EOF.
            int length = (
                  Byte.toUnsignedInt(bytes[0])
                

        System.out.println("End of file.");
    


private static void printDescriptor(byte[] bytes)
        throws IOException 
    String desc = new String(bytes, "US-ASCII");
    System.out.println("Found '" + desc + "' descriptor.");

Por ejemplo, aquí hay un archivo WAV aleatorio que tenía:

Found 'RIFF' descriptor.
Found 'bext' descriptor.
Found 'fmt ' descriptor.
Found 'minf' descriptor.
Found 'elm1' descriptor.
Found 'data' descriptor.
Found 'regn' descriptor.
Found 'ovwf' descriptor.
Found 'umid' descriptor.
End of file.

En particular, aquí tanto 'fmt' como 'data' aparecen legítimamente entre otros fragmentos porque la especificación RIFF de Microsoft dice que los subchunks pueden aparecer en cualquier orden. Incluso algunos de los principales sistemas de audio que conozco se equivocan y no tienen en cuenta eso.

Entonces, si desea encontrar un cierto fragmento, recorra el archivo verificando cada descriptor hasta que encuentre el que está buscando.

El truco consiste en mirar el "Subchunk1Size", que es un entero de 4 bytes que comienza en el byte 16 del encabezado. En un wav normal de 44 bytes, este entero será 16 [10, 0, 0, 0]. Si es un encabezado de 46 bytes, este entero será 18 [12, 0, 0, 0] o tal vez incluso más si hay metadatos extra extensibles (¿poco común?).

Los datos adicionales en sí (si están presentes) comienzan en el byte 36.

Entonces, un programa C # simple para detectar la longitud del encabezado se vería así:

static void Main(string[] args)

    byte[] bytes = new byte[4];
    FileStream fileStream = new FileStream(args[0], FileMode.Open, FileAccess.Read);
    fileStream.Seek(16, 0);
    fileStream.Read(bytes, 0, 4);
    fileStream.Close();
    int Subchunk1Size = BitConverter.ToInt32(bytes, 0);

    if (Subchunk1Size < 16)
        Console.WriteLine("This is not a valid wav file");
    else
        switch (Subchunk1Size)
        
            case 16:
                Console.WriteLine("44-byte header");
                break;
            case 18:
                Console.WriteLine("46-byte header");
                break;
            default:
                Console.WriteLine("Header contains extra data and is larger than 46 bytes");
                break;
        

Además de la excelente respuesta de Radiodef, me gustaría agregar 3 cosas que no son obvias.

  1. La única regla para los archivos WAV es que el fragmento FMT viene antes que el fragmento DATA. Aparte de eso, encontrará fragmentos que no conoce al principio, antes del fragmento de DATOS y después. Debe leer el encabezado de cada fragmento para saltar hacia adelante y encontrar el siguiente fragmento.

  2. El fragmento FMT se encuentra comúnmente en variaciones de 16 bytes y 18 bytes, pero la especificación también permite más de 18 bytes. Si el campo de tamaño de encabezado del fragmento FMT dice mayor que 16, los bytes 17 y 18 también especifican cuántos bytes adicionales hay, por lo que si ambos son cero, terminará con un fragmento FMT de 18 bytes idéntico al de 16 bytes. Es seguro leer solo los primeros 16 bytes del fragmento FMT y analizarlos, ignorando los más. ¿Por qué importa esto? - ya no mucho, pero el Media Player de Windows XP podía reproducir archivos WAV de 16 bits, pero archivos WAV de 24 bits solo si el fragmento FMT era la versión Extendida (18+ bytes). Solía ​​haber muchas quejas de que "Windows no reproduce mis archivos WAV de 24 bits", pero si tuviera un fragmento FMT de 18 bytes, lo haría ... Microsoft lo solucionó en algún momento durante los primeros días de Windows 7, por lo que Los archivos FMT de 24 bits con 16 bytes funcionan bien ahora.

  3. (Recién agregado) Los tamaños de trozos con tamaños impares ocurren con bastante frecuencia. Se ve principalmente cuando se crea un archivo mono de 24 bits. No está claro a partir de la especificación, pero el tamaño del fragmento especifica la longitud real de los datos (el valor impar) y se agrega un byte de relleno (cero) después del fragmento y antes del inicio del siguiente fragmento. Por lo tanto, los fragmentos siempre comienzan en límites pares, pero el tamaño del fragmento en sí se almacena como el valor impar real.

Al final de la artículo puedes encontrar las referencias de otros creadores, tú igualmente tienes la opción de dejar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *