PDA

Ver la Versión Completa : Datos interpaginados a array


Guillermo80
31-05-2008, 13:54:03
Hola, tengo una aplicación que me funciona bien, pero teóricamente no entiendo del todo cómo lo hace, me explico: se trata de alimentar un codificador de audio, al cual le llega un array tipo byte con las muestras interpaginadas de los canales L y R. Para ello primero voy leyendo el wav de entrada, que voy guardando a cada pasada del bucle, con Blockread, guardo en un array bufer de 2*n posiciones. Después con otro bucle interno al primero se van interpaginando las muestras guardándose en otro array pcm de mitad de tamaño, o sea, n. Cuando termina este subbucle, coge y alimenta al codificador. Para que se entienda, voy a poner el trozo de código que interesa:


...dentro de un while, ya llego aqui con las muestras leídas del wav al array buffer...

for i:=0 to (necesarias*channels-1) do
begin

pcm[i] := buffer[2*i+1] shl 8 or buffer[2*i];
end;
//se alimenta el codificador
ok := FLAC__stream_encoder_process_interleaved(pencoder, pcm, necesarias);

...sigue dentro del while más operaciones y luego vuelta a empezar...Dentro del for va guardando en pcm las posiciones impares según entiendo, pero lo que no entiendo es el porqué del desplazamiento shl, y la función del or, no entiendo en qué caso cogería buffer[2*i]

No pongo más segmentos de código porque no interesa saber nada más que lo que aquí muestro. La clave está en por qué utilizo un bufer de mitad de tamaño para interpaginar las muestras, cómo se interpaginan dentro del for, o sea, cuándo se cogen las pares.

ixMike
31-05-2008, 15:14:13
¿Es mi impresión, o el array llamado PCM va a ser el contenido del audio en mono? No sé, igual estoy algo confundido, pero eso de que opere con buffer[2*i+1] y buffer[2*i] da toda la impresión de que se estén mezclando ambos canales, en ese caso la operación adecuada para sumar ambos canales sea esa con shl y or.

Salu2, y perdón si sólo estoy confundido y no te he ayudado :(.

Guillermo80
31-05-2008, 19:17:53
Hola ixMike, gracias por tu interés, estás cerca de dar con la clave, mira te explico un poco mejor ahora que he estado repasando un poco:

buffer recordemos que es un array de bytes, o sea, cada posición, un byte.
EL flujo de datos wav que se va a almacenar en buffer va así, sabiendo que una muestra de un canal ocupa 2bytes:

2bytes canal L, 2bytes canal R, 2bytes canal L, 2bytes canal R, ....Por lo tanto en buffer quedará así almacenado:

1byte L, 1byte L, 1byte R, 1byte R, 1byte L, 1byte L, 1byte R, 1byte R, ...Ostras, a medida que escribo creo que lo voy entendiendo yo también, ahora viene la instrucción que va dentro del bucle for, que a mi entender, es de mitad de tamaño porque agrupa en una posición las muestras de buffer i e i+1 de un canal en una posición de pcm, y esto lo hace gracias al desplazamiento de 8 bits (1byte) a la izquierda de la muestra i, que concatena a su derecha la muestra i+1:


pcm[i] := buffer[2*i+1] shl 8 or buffer[2*i];
Ahora, creo que eso es así, pero no entiendo cómo funciona el operador or en esta situación de trabajar bit a bit, ¿podrías explicármelo para terminar de entender cómo en una misma instrucción hace lo que he explicado?:)

Al González
31-05-2008, 19:59:21
¡Hola!

...no entiendo cómo funciona el operador or en esta situación de trabajar bit a bit...

Suponiendo que tienes un byte B1 con un valor decimal de 20 (en binario, 00010100) y segundo byte B2 con un valor decimal de 12 (en binario, 00001100), la expresión B1 Or B2 te devolverá un entero de valor decimal 28 (en binario, 00011100).

00010100 (20)
Or
00001100 (12)
------------------
00011100 (28) <-- (se integró el bit de valor 8 al los bits de 20)

Or toma todos los bits activos (los que están en 1) de ambos operandos.

And toma todos los bits que estén activos en ambos operandos.

XOr toma todos los bits que estén activos en alguno de los operandos pero inactivos en el otro.

Espero te sirva de algo esta modesta explicación.

Un saludo Or abrazo.

Al González. :)

Guillermo80
31-05-2008, 20:18:48
Hola Al, sólo tengo que decirte que tu explicación encaja como un guante, ahora entiendo cómo trabaja el bloque completo. Hacía tiempo que no usaba or para sumar bits, estaba obcecado pensando en "el otro or", o sea, o cojo la expresión evaluada a la izquierda o la de la derecha (es que hoy estoy espeso).

Bueno, pues dejo la explicación final y resumida:para una muestra de un canal tenemos 2bytes, al más significativo lo corro 8 bits a la izquierda con shl 8, y a continuación se le suma con el operador or el byte menos significatico, cuyo resultado va a una posición del array pcm. Para una muestra completa de una posición de pcm resultaría del siguiente ejemplo:

byte1 + byte2 = muestra completa canal L
byte1 = 11000001; byte2 = 01010001
Tomando que el byte1 debe ser el más significativo, debe ser el que desplacemos 8 bits a la izquierda:

muestra1 equivalente = 1100000100000000 (habrá que guardarlo en un entero)

Ahora hago la suma de ambas muestras (guardadas en variables tipo entero):

1100000100000000
0000000001010001 +
--------------------
1100000101010001 --> será una muestra del array pcm, de tipo entero

¡ Todo encaja ! Gracias a los dos :p