Ayuda con un concepto de una API

Antes de ir al Soporte consultame aquí, gracias
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

Puse el post aquí, porque al ser básicamente un concepto de la documentación de una API lo que no entiendo...
Pointer to a variable to be filled with the current volume setting. The low-order word of this location contains the left-channel volume setting, and the high-order word contains the right-channel setting. A value of 0xFFFF represents full volume, and a value of 0x0000 is silence.
Esto lo he visto en varias APIS de este grupo (WaveOut) y no termino de entender que significa:
The low-order word of this location contains the left-channel volume setting, and the high-order word contains the right-channel setting.
entiendo el significado de la frase, pero no como aplicarlo a Autoit.
¿qué es eso de "palabra de órden inferior", y "Categoría alta"?.

bueno: así me lo ha traducido el traductor de Yahoo esta parte que no sabía bien como traducirla. Seguro, que tiene una traducción mejor, que podría dejar más claro que es, pero ... teniendo en cuenta que:
Pointer to a variable to be filled with the current volume setting. The low-order word of this location contains the left-channel volume setting, and the high-order word contains the right-channel setting. A value of 0xFFFF represents full volume, and a value of 0x0000 is silence.
viene a decir que almacena el ajuste del volumen actual en una variable, no entiendo eso de
The low-order word of this location contains the left-channel volume setting, and the high-order word contains the right-channel setting.
que vale, el valor que almacene la API en la variable que le indiquemos, contiene el volumen del canal izquierdo y derecho; pero ¿como obtengo cada valor?...
Ya veo, que el contenido de la variable será un valor hexadecimal, pero no se que tengo que hacer con eso, para saber el volumen de un canal determinado (izquierdo o derecho).

la documentación completa está en:

http://msdn.microsoft.com/en-us/library/aa909806.aspx

Acias,

Salu2!
Avatar de Usuario
Alastor
Aprendiz de Mago
Mensajes: 59
Registrado: 13 Dic 2009, 14:27
Ubicación: Zaragoza, España
Contactar:

Re: Ayuda con un concepto de una API

Mensaje por Alastor »

La parte alta y baja de un DWORD (double word) son las dos partes que la forman:
(DWORD)0x12345678
(WORD)0x1234 -> Parte alta del dword
(WORD)0x5678 -> Parte baja del dword

Para obtener la parte que te interese seria suficiente con utilizar un AND logico (En AutoIt se utiliza la funcion BitAnd).

Por ejemplo, para obtener la parte baja se haria un And con 0x0000FFFF

Código: Seleccionar todo

BitAnd(0x12345678, 0x0000FFFF) ; Daria como resultado 0x00005678 que es el volumen de uno de los altavoces.
Para obtener la otra parte se haría un BitShift:

Código: Seleccionar todo

BitShift(0x12345678, 16) ; Daria como resultado 0x1234 -> el volumen del otro altavoz
PD: No se si en AutoIt hay alguna funcion para hacerlo mas facilmente ya que nunca lo he usado en AutoIt...
Última edición por Alastor el 17 Ene 2011, 18:32, editado 1 vez en total.
Aprendiendo AutoIt y C++
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con un concepto de una API

Mensaje por Chefito »

Todo perfecto Alastor. Estás hecho una máquina :smt002 .
Lo único puntualizar que Alastor lo ha explicado para un dato de tipo dword (4 bytes), y éste tiene un tamaño de 2 bytes (podría ser un tipo word). El puntero que apunta al dato es el que tiene tipo dword. Pero el verdadero dato es de 2 bytes de tamaño (que será el valor que recupere).
En este caso el volumen se representa con valores que van comprendidos desde el silencio (0) al volumen maxímo (255=0xff).
Al ser de dos bytes (dos altavoces, un byte por cada altavoz), el tamaño es de 0x0000 a 0xffff. Divide por ejemplo el número 0x1234 en dos partes iguales, los dos de la izquierda son la parte alta del número porque son los valores que más pesan (12), y los dos de la derecha son la baja, son los valores que menos pesan (34).

Para que sepas que significa eso del peso te voy a dar un ejemplo con un número decimal: 1234.
La parte que más pesa es 12 porque 1 es unidad de mil (1000) y 2 es centena (200), y la que menos pesa es el 34 porque 3 es decena (30) y 4 es unidad (4).

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Alastor
Aprendiz de Mago
Mensajes: 59
Registrado: 13 Dic 2009, 14:27
Ubicación: Zaragoza, España
Contactar:

Re: Ayuda con un concepto de una API

Mensaje por Alastor »

Gracias por la corrección, he pensado que seria un DWORD ya que es lo mas habitual.
Aprendiendo AutoIt y C++
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

¡Muchas gracias a los dos!.

Muy buenas explicaciones ambas. otra cosa más que aprendo; si hasta va a ir bien eso de tocar APIS :).

¡Gracias Chefito por ese ejemplo en decimal! :).

Imagino, que el valor hexadecimal que reciba siempre será par? (por eso de dividirlo en dos partes iguales) (estoy en eso de dominar la representación hexadecimal de números decimales) :P.
¿la división la he de hacer con alguna función Bit() como decía Alastor, o no es necesario?...

Por cierto,"0x", no cuenta a la hora de hacer la división del número, por lo que he visto ¿verdad?.

Acias,

Salu2!
Avatar de Usuario
Alastor
Aprendiz de Mago
Mensajes: 59
Registrado: 13 Dic 2009, 14:27
Ubicación: Zaragoza, España
Contactar:

Re: Ayuda con un concepto de una API

Mensaje por Alastor »

0x indica que el número está en hexadecimal.

Si que debes usar las funciones que he dicho, ya que son operaciones sobre bits.

Tal como ha dicho Chefito, tendrias que hacer lo que he dicho al principio, pero teniendo en cuenta solo la mitad del dato:

Aqui tienes un ejemplo para que lo entiendas:

Código: Seleccionar todo

$Dw = DllStructCreate("word")
DllCall("Winmm", "int", "waveOutGetVolume", "int", 0, "long", DllStructGetPtr($Dw))

$Altavoz_L = BitAnd(DllStructGetData($Dw, 1), 0x00FF)
$Altavoz_H = BitShift(DllStructGetData($Dw, 1), 8)

MsgBox(0, "", "Volumen izquierdo = " & $Altavoz_L & @CRLF & "Volumen derecho = " & $Altavoz_H)
Aprendiendo AutoIt y C++
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

Ajá, ahora sí, entiendo. porque la api me devolvía en la estructura 0x0000FFFF, y no sabía bien qué hacer con eso ... :P.

la teoría de qué es el byte más alto y más bajo, y como se calcula la he entendido. lo que no me queda tan claro, es hacerlo con Bitand() y bitShift(), porque nunca he entendido esas funciones, aunque me hago una idea de qué hacen. BitAnd() por ejemplo, creo que es el operador & de C++ (Y) a nivel de bit ¿verdad?...

Pero ando muy pegao del tema binario :).

¡Acias por el ejemplo!

Salu2!
Avatar de Usuario
Alastor
Aprendiz de Mago
Mensajes: 59
Registrado: 13 Dic 2009, 14:27
Ubicación: Zaragoza, España
Contactar:

Re: Ayuda con un concepto de una API

Mensaje por Alastor »

En efecto, AND es el operador & de C/C++. Y el de BitShift es << o >> dependiendo de la dirección.
¿Por qué AND?
Al hacer AND entre dos números (binarios) solo permanecerán a 1 los bytes que esten en ambos números:

Código: Seleccionar todo

Numero 1 (binario)         =   01010101
Numero 2 (binario)         =   00001111
AND entre ellos (binario)  =   00000101
En el caso del volumen, solo queremos los 2 bytes a la derecha del numero, por lo tanto filtramos los que no queremos mediante AND:
(Lo pongo en hexadecimal ya que es mas rapido que poner todos los bits)

Código: Seleccionar todo

Numero 1          = 0x01111101
Numero 2          = 0x0000FFFF
AND entre ellos   = 0x00001101
Como ves, nos libramos de la parte del word que no queremos y asi tienes uno de los volúmenes.

En el caso de la otra parte de la word, tenemos que utilizar BitShift para mover de posición los bits:
Primero decir que un DWORD esta formado por 32 bits y un WORD por la mitad (16), si solo queremos los bits de la izquierda, basta con moverlos a la derecha (BitShift):
Numero (WORD) = 0x12FF
Al mover sus bits 8 posiciones a la derecha quedaria "0x0012" que es la parte que nos interesa.

Espero no haberlo explicado muy confuso, estoy con un trabajo de clase y por lo tanto bastante estresado D:
Aprendiendo AutoIt y C++
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Que va, ¡perfecto!.

Así, ya voy sabiendo mejor qué hago usando esas funciones, que siempre es mejor que copiarlas sin saber que hace, como funcionan :P.

Nada como haber tocado C/c++, para entender bien todo esto! :).

¡Acias!

Salu2!
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

después de entender mejor esto de byte más alto y más bajo, las apis siguen poniéndome a prueba (menos mal que ya casi termino con la librería) :).

Si bien antes de un número tenía que separar el byte más alto y el más bajo para obtener por ejemplo el volumen de los altavoces, ahora, para ajustar el volumen de estos, he de hacer lo contrario.
He de dar un valor, donde el byte más alto es el altavoz derecho, y el más bajo el izquierdo.

Como estoy implementando las apis en una UDF he querido hacer las funciones lo más flexibles posibles, por lo que en la función que ajusta el volumen de los altavoces: WaveOutSetVolume() he puesto dos argumentos: uno para el altavoz izquierdo, y otro para el derecho. De manera, que digamos, tengo el byte más alto y más bajo y con eso he de hacer un entero que he de pasar a la api waveOutSetVolume:

http://msdn.microsoft.com/en-us/library/aa908146.aspx

diría, que he de coger los dos argumentos que he puesto en la función que estoy haciendo (valor del altavoz izquierdo y valor del altavoz derecho) y hacer algo como:

Código: Seleccionar todo

BitOr($ArgLeftChannelVol, $ArgRightChannelVol)
aunque como no domino aún mucho eso de las funciones Bit() no se si será exactamente así... ¿sería así?

Imagino, que el byte más alto será el altavoz derecho y el más bajo el izquierdo, según pone en la documentación:
Specifies a new volume setting. The low-order word contains the left-channel volume setting, and the high-order word contains the right-channel setting.
Si mi inglés no falla... aunque pensaba que sería al revés :).

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con un concepto de una API

Mensaje por Ximorro »

Si haces un OR (o AND o XOR, etc.) se opera con los bits y se obtiene un resultado del mismo tamaño, así que es imposible concatenar los bytes con eso.

Se hace por ejemplo así:

Código: Seleccionar todo

$enteroCorto = $byte_alto * 256 + $byte_bajo
Claro que realmente en AutoIT no es un entero corto, pues AutoIt no tiene tipos especificados por el usuario e internamente usa enteros de 4 bytes u 8 bytes sin que lo podamos remediar, esto no será un problema para pasarlo a una DLL, pues DLLCall lógicamente se encargará de hacer la conversión y enviar los dos bytes bajos que interesa.

Por cierto si nos empeñamos en hacerlo con operaciones de bits se puede hacer así:

Código: Seleccionar todo

$enteroCorto = BitOr(BitShift($byte_alto, -8), $byte_bajo)
Pero en este caso es mucho mejor la expresión artitmética, es muchísimo más rápida en AutoIt. El resultado es exactamente el mismo.

Por cierto, ese enlace que has puesto es de Windows Mobile ¿estás ejecutando AutoIt en un WindowsMobile?

Y otro por cierto, AutoIt tiene un SoundSetWaveVolume, es de AutoIt base, ni siquiera hace falta una UDF. Es para dar el volumen para el script en ejecución. Si la otra función hace exactamente eso no hace falta que hagas un "wrapper" para la DLL, se la haces a la función de AutoIt y ya está :smt003
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

Thanks, no iba del todo desencaminado con el BitOr(), aunque a mi también me gusta más, hacerlo de la otra manera si da el mismo resultado.
Ximorro dijo: Por cierto, ese enlace que has puesto es de Windows Mobile ¿estás ejecutando AutoIt en un WindowsMobile?
:). No, en Windows XP. Me parece raro desde que estoy tocando estas apis, pero en todas las funciones de este grupo de la api pone que son para Windows mobile, aunque en Win XP (no se si en Vista/Siete también) está la librería Winmm.dll.
Ximorro dijo: Y otro por cierto, AutoIt tiene un SoundSetWaveVolume, es de AutoIt base, ni siquiera hace falta una UDF. Es para dar el volumen para el script en ejecución.
Si la otra función hace exactamente eso no hace falta que hagas un "wrapper" para la DLL, se la haces a la función de AutoIt y ya está
Bueno; WaveOutSetVolume, lo que hace es, ajustar el volumen para la instancia del dispositivo de sonido que le indiques.
Vamos, no afecta a todo el sistema (a menos que le pases el identificador del dispositivo en vez del handle).
También, como puse en el otro post, se puede ajustar (si el dispositivo de sonido lo soporta) el volumen de los altavoces por separado, consiguiendo así si se quiere hacer balanceo de sonido...

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con un concepto de una API

Mensaje por Chefito »

Recuerda este post que puse para hacer este tipo de cosas y muchas más. Puede que así te sea más facil manejar sonidos: http://www.emesn.com/autoitforum/viewto ... 1296#p7600

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

Interesante el post.

Antes de empezar con las funciones WaveOut, estuve mirando la api mciSendString, ya que mirando la UDF Sounds.au3 vi que usaban esa función.

Lo que pasa, es, que necesitaba reproducir un sonido que estuviera en un buffer, en vez de en un archivo. Y aunque en algunas páginas leí algo de que pudiera hacerse, no llegué a encontrar como.

Además, no encontré en la msdn la api, y eso de que se le pudieran mandar tantos mensajes se me hizo un mundo.
Así que, buscando y buscando, fui a dar con las apis WaveOut, que he acabado implementando, que seguramente son mucho más complejas al fin y al cabo que mciSendString...

Por fin la UDF está terminada (faltan dos funciones que no he implementado porque no encuentro algunas constantes por ningún sitio).

En cuanto la repase y arregle alguna cosilla que no entendía a la hora de implementar las apis y que me habeis ido explicando por aquí, la colgaré en el foro por si a alguien le interesa. (seguro que puede mejorarse bastante) pues no es que sea muy bueno con el sonido y el inglés :).

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con un concepto de una API

Mensaje por Ximorro »

¿No ibas desencaminado? ¿lo entiendes ahora?

¿Vas probando las funciones según las vas mapeando?
Mira que aunque las DLL se llamen igual no quiere decir que todos los sistemas tengan la misma interfaz... Normalmente si pasas a un sistema más moderno en el mismo dispositivo (por ejemplo a Vista desde XP) la librería puede ser ampliada pero probablemente mantiene la compatibilidad. Pero si pasas a otro tipo de dispositivo (un móvil) puede que no tengan la misma funcionalidad...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola
Ximorro dijo: ¿No ibas desencaminado? ¿lo entiendes ahora?
Bueno, yo dige que creía que debía hacerlo con BitOr():
Jonny dijo: He de dar un valor, donde el byte más alto es el altavoz derecho, y el más bajo el izquierdo.

Como estoy implementando las apis en una UDF he querido hacer las funciones lo más flexibles posibles, por lo que en la función que ajusta el volumen de
los altavoces: WaveOutSetVolume() he puesto dos argumentos: uno para el altavoz izquierdo, y otro para el derecho. De manera, que digamos, tengo el byte
más alto y más bajo y con eso he de hacer un entero que he de pasar a la api waveOutSetVolume:

http://msdn.microsoft.com/en-us/library/aa908146.aspx

diría, que he de coger los dos argumentos que he puesto en la función que estoy haciendo (valor del altavoz izquierdo y valor del altavoz derecho) y hacer
algo como:

Código: Seleccionar todo

BitOr($ArgLeftChannelVol, $ArgRightChannelVol)
y respondiste:
Ximorro dijo: Por cierto si nos empeñamos en hacerlo con operaciones de bits se puede hacer así:

Código: Seleccionar todo

$enteroCorto = BitOr(BitShift($byte_alto, -8), $byte_bajo)
:)

No es que lo entienda, pero usas la función BitOr(), aunque yo me dejé la función BitShift() :).

Sí, claro que pruebo las funciones a medida que las voy haciendo y funcionan... De hecho, he visto algún código de otros programas escritos en otros lenguajes, que utilizan estas funciones, y en el foro inglés de AutoIt hay alguna función implementada de esta librería.

Salu2!
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

hola

Pensaba que había entendido como funcionaban las funciones bit y como hacer eso del bit más alto y más bajo... pero no me aclaro con BitAnd().

En el ejemplo de alastor, donde obtiene el volumen de uno de los altavoces con BitAnd(), pone 255 en hexadecimal en el segundo parámetro de la función.
pero ¿si no se el valor máximo?. Porque en ese caso, sí se sabe que el máximo de volumen es 255, pero hay funciones en las que la documentación no dice cual es el valor máximo ni mínimo. Solo, que 0x8000 es la mitad. Entiendo que 0x8000*2 será el máximo, pero no me da el resultado correcto. Pues en la función WaveOutGetPitch pone como ejemplo, que 0x00010000 sería 1.0 y 0x000F8000 sería 15.5.
pdwPitch
Pointer to a variable to be filled with the current pitch multiplier setting. The pitch multiplier indicates the current change in pitch from the original authored setting. The pitch multiplier must be a positive value.

The pitch multiplier is specified as a fixed-point value. The high-order word of the variable contains the signed integer part of the number, and the low-order word contains the fractional part. A value of 0x8000 in the low-order word represents one-half, and 0x4000 represents one-quarter. For example, the value 0x00010000 specifies a multiplier of 1.0 (no pitch change), and a value of 0x000F8000 specifies a multiplier of 15.5.
Ahí me he quedao encallao :).

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con un concepto de una API

Mensaje por Chefito »

Vamos a ver, más que no entender el concepto te falta saber hexadecimal.

Según lo que dice ahí, divide una palabra de 32 bytes en dos partes de 16 bytes (como siempre la parte más baja de la palabra es un dato, en este caso la parte decimal, y la más alta otro, la parte entera).
Por eso la palabra 0x00010000=1, porque separando la parte entera 0x0001=1 de la parte decimal 0x0000=0 (1.0=1).
Te pone otro ejemplo: 0x000f8000. Si las separamos:
0x000f=15, parte entera del número.
0x8000=0,5 parte decimal. Es 0,5 porque es la mitad del valor máximo que puede tener esta parte de la palabra (0xffff) y el mínimo (0x0000).

Por esta causa 0x000f8000=15,5.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Ayuda con un concepto de una API

Mensaje por Jonny »

Hola

gracias por la explicación.

Es algo así como lo que me explicaste con los números decimales, hace algunos días ¿no?, pero explicando como funciona el sistema hexadecimal.

El problema, es, que no se separar el byte más alto y más bajo de un valor, sea en decimal o hexadecimal.

En el ejemplo del volumen de los altavoces, era algo como:

bitand($valor, $volumenmaximo) que el volumen máximo de los altavoces era 255, pero en este caso ¿cual es el máximo (digo yo que debe ser de la parte decimal)? 10 ¿no? (si la mitad es 5).

como sería para obtener el byte más bajo (parte fraccionaria):

Código: Seleccionar todo

bitand($valor, 10)
¿da lo mismo si se pone el 10 en decimal o hexadecimal en bitand ¿verdad?.

de todas formas, según la API los drivers que tengo instalados no son compatibles con esta función.... Así, que no lo puedo probar a ver si lo hago bien...

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con un concepto de una API

Mensaje por Chefito »

Se separa como te dice Alastor en el post anterior: http://www.emesn.com/autoitforum/viewto ... 2465#p9927

Es independiente que utilices número hexadecimales o decimales para cualquier cosa que programes. AutoIt se encarga de interpretarlo.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Responder