Stratégie pour décaler des bits

Résolu
Utilisateur anonyme - 7 mai 2008 à 11:48
 Utilisateur anonyme - 10 mai 2008 à 13:35
Salut la compagnie ,

Je travaille sur les fichiers midi : les évènements midi utilisent un paramètre qui est un DeltaTime et qui peut (et doit ) codé sur 32 bi</gras>. Sauf qu'il y a un sauf  (ben oui sinon c'est pas drole).

Z'explique le truc :

Prenons un longword bidon :

10000001   10110001   10110001   1010001

Selon la norme Midi il faut sucré pour chaque Bytes le premier bit (ou le dernier si on va de la gauche vers la droite)

On obtient donc ceci

(1)0000001   (1)0110001   (1)0110001   (1)010001

On rafistole le tout (Encore un truc à la Mac Gyver ) :

On obtient  0000001 0110001  0110001 010001

On remplace les bits "perdus" par des zéros

On obtient : 0000 0000001 0110001  0110001 010001

Même si je connais les opérateurs binaires, je n'ai aucune idée de comment faire la chose.

Merci à vous

26 réponses

f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
9 mai 2008 à 14:40
masquage du 7 eme bit :

byte : $7F (1000-0000)
word: $7F7F (1000-0000-1000-0000)
longword : $7F7F7F7F
int64 : $7F7F7F7F7F7F7F7F

pouf

masque bit 0
$E

masque bit 1
$D

masque bit 2
$B

masque bit 3
$7

et comme les bits se repete en hexa par mot de 4 bits ...

masque bit 4
$EF

masque bit 5
$DF (SDF lol)

masque bit 6
$BF

masque bit 7
$7F

etc...

et on repetre pour du 16, 32, 64 bits.

ensuite pour tout ce qui est decalage/rotation :

assembleur : SHL, SHR, ROL, ROR
+ pour manipuler les octets : XCHG, BSWAP

3
Utilisateur anonyme
10 mai 2008 à 13:35
Salut,

Je tiens à tous vous remercier pour votre aider. Merci aux personnes qui m'ont aidé en privé (Twinuts, Sheorogath, Philippe).

Voila la procédure pour écrite la variable Length Quantitie :

Procedure WriteVLQ(Value:Word;MS:TMemoryStream);
Var
  Buffer, Count, Index:Word;
Begin
  Buffer:=Value AND $7F;
  Value:=Value SHR 7;
  Count:=0;
  While Value>0 Do
    Begin
      Buffer:=Buffer SHL 8;
      Buffer:=Buffer OR $80;
      Buffer:=Buffer+ (Value AND $7F);
      Value:=Value SHR 7;
      Inc(Count);
    End;
  For Index:=Count DownTo 0 Do
    Begin
      MS.Write(Buffer,1);
      Buffer:=Buffer SHR 8;
    End;
End;

Désolé d'avoir été un peu lourd mais sans ce fichu delta time, je ne pouvais plus avancer
3
Utilisateur anonyme
7 mai 2008 à 13:13
Salut Cirec : j'ai vu cette source mais elle ne fait pas avancer rmon schmilblic .
0
Tavounet Messages postés 7 Date d'inscription mercredi 16 avril 2008 Statut Membre Dernière intervention 19 mai 2008
7 mai 2008 à 13:13
J'ai été voir le lien sur ta réponse cirec et là, il me semble que le problème est bien plus complexe, il ne s'agit pas d'une vulgaire opération. ^^

Francky, est-ce que tu peux récupérer tes bits un par un?
Si oui, j'ai peut-être une idée.

Tu pars d'un longword 00000000 00000000 00000000 00000000.

Tu récupères le premier bit puis tu décales ton longword à droite en insérant le bit récupéré.

Idem pour le deuxième, troisième...

Tu as juste à "sauter" les 1 que tu veux virer.

Une fois tes 28 bits récupérés, tu fais un décalage à droite avec insertion de 0 quatre fois, et tu obtiendras ta valeur normalement.

Je ne sais pas si ça fonctionne, mais à tester ^^

Bon courage 
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
7 mai 2008 à 14:04
Salut

En fait je ne récupère pas les messages midi : c'est pour faire un fichier midi.
Un lien pourles explications .

Si l'utilisateur veut ajouter une note : la procédure suivante est lancée :
procedure TMidiWriter.Add_NoteOn_Event(Const DeltaTime : LongWord; Const Channel, KeyNumber, Velocity: byte);
Et là il faut transformer le Delta Time en virant les premiers bits.

Pour être honnète j'ai trouvé ceci :

void WriteVarLen (register long value)
{
register long buffer;
buffer = value & 0x7f;
while ((value >>= 7) > 0)
{
buffer <<= 8;
buffer |= 0x80;
buffer += (value & 0x7f);
}
while (TRUE)
{
putc(buffer & 0xFF,outfile);
if (buffer & 0x80)
buffer >>= 8;
else
break;
}
}

doubleword ReadVarLen ()
{
register doubleword value;
register byte c;
if ((value = getc(infile)) & 0x80)
{
value &= 0x7f;
do
{ value (value <<7) + ((c getc(infile)) & 0x7f);
} while (c & 0x80);
}
return (value);
}

Manque de bol c'est du C donc j'y comprend que dalle et cette saloperie d'opérateur <<= je l'ai trouvé nul part donc je sais pas ce que c'est.

Merci A++
.
0
Utilisateur anonyme
7 mai 2008 à 14:50
Salut Cari : la fonction de f0xi AllToBinStr(const Buffer; const bSize : integer; var OutBinStr : string); pourrait éventuellement me dépanner. Mais je trouve ca lourd tout ca pour déplacer 4 octets . Ca fait pas propre à mon gout (Je sais je suis chiant mais apres c'est qui qui va se faire gronder quand il va poster le source???? C'est francky ).

Je vais voir du coté de l'Assembleur (En même temps mon pc est plus sous garantis donc j'hésite : l'asm peut etre dangereux  sous les mains de Francky )
0
Utilisateur anonyme
7 mai 2008 à 14:51
Pardon 4 bits (une fonction éditer serait la bienvenue )
0
cs_Kenavo Messages postés 702 Date d'inscription vendredi 21 mars 2003 Statut Membre Dernière intervention 1 octobre 2009 5
7 mai 2008 à 16:05
Elle est où la contrepèterie dans le titre ??




procedure Virons4Bits (var v: longword);
begin
  v := v and $7F7F7F7F;
  v : = (v+ v and $7F) div 2;      // 2^7 - 1
  v := (v + v and $3FFF) div 2;   // 2^14 - 1
  v : = (v + v and $1FFFFF) div 2; // 2^21 - 1


end;






C'est pour décaler les sons ??

Ken@vo








Code, Code, Codec !
0
Utilisateur anonyme
7 mai 2008 à 16:22
Non Kenavo c'est pour formater le paramètre Delta Time des midis . Ta procédure supprime des bits mais pas les bons  : je vais regarder cela ce soir
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
7 mai 2008 à 16:28
Delphi, c'est mieux que de compiler le C.
0
cs_Kenavo Messages postés 702 Date d'inscription vendredi 21 mars 2003 Statut Membre Dernière intervention 1 octobre 2009 5
7 mai 2008 à 16:33
Ou alors :

procedure Virons4BitsEncore(var v : longword);
type
  TTabByte = array [0..3] of byte;
var
  TByte : TTabbyte absolute v; // TByte et v partagent les mêmes octets
begin
  v: = Tbyte[0] and $7f + (Tbyte[1] and $7f)*$80 + (Tbyte[2] and $7f)*$4000 + (Tbyte[3] and $7f)*$200000;
end;

Ken@vo







Code, Code, Codec !
0
cs_Kenavo Messages postés 702 Date d'inscription vendredi 21 mars 2003 Statut Membre Dernière intervention 1 octobre 2009 5
7 mai 2008 à 16:38
Vérifie Francky !
(et ne me dit pas que le dernier octet du longword est est réellement un septet comme dans ton exemple)

Ken@vo








Code, Code, Codec !
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
7 mai 2008 à 21:06
Alors mon lien n'était pas bon ... hein ^^

et il a utilisé quoi Kenavo alors
me semble bien que ce sont des opérateurs logiques

 
@+
Cirec

<hr siz="" />
0
Utilisateur anonyme
7 mai 2008 à 21:10
Ah ben celle la elle est bonne : un message vide.

J'ai fais un test : 11111111 11111111 11111111 11111111 devient
11111111 11111111 11111111 00001111.

Désoé Kénavo mais c'est pas bon ;).

@Cirec : mais j'ai pas dis qu'il ne fallait pas utiliser les opérateurs logiques mais le probleme c'est que c'est truc là j'y arrive jamais
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
7 mai 2008 à 22:57
tiens bizzare j'obtiens pas la même chose que toi ???? :




Départ :=  11111111 11111111 11111111 11111111


Arivée :=   1111111 1111111 1111111 1111111





 






@+
Cirec





<hr siz="" />
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
7 mai 2008 à 23:09
et en corrigant l'erreur de ton exemple (si c'est réellement une erreur) de Septet en Octet
ça le fait très bien ^^
10000001 10110001 10110001 10110001 Devient

1 0110001 0110001 0110001

Alors Septet ou Octet ?

 
@+
Cirec

<hr siz="" />
0
Utilisateur anonyme
8 mai 2008 à 04:56
Salut,

"10000001 10110001 10110001 10110001  Devient

1  0110001  0110001  0110001"

Vous avez pas compris En fait il faut supprimer les premiers bits de chaque octet, coller ce qui reste. Et mettre à gauche 4 zéros pour tomber sur 32 bits.

"Since 81 is larger than 80, you can see that the 00 byte is also
part of the VLV. Lets look at 81 00 in binary notation:
10000001 00000000


Separate the continuation bit from the data bits:
1 0000001 0 0000000


Now you can see in binary notation what you can also see in hex notation --
that the first byte expects at least one more byte to follow it in the VLV.
Remove the continuation bits:
0000001 0000000


This is the actual number that is represented by the VLV value <tt>81 00</tt>,
but maybe we should convert to decimal or hex so you understand it better.
First, combine all of the bits into one clump:
00000010000000


I will convert first to hexadecimal, and later to decimal. For hexadecimal
conversion of a binary number, arrange the digits into groups of 4, starting
with the least siginificant (smallest, right) side of the number:
00 0000 1000 0000


There are two zeros left on the left size, so add two more zeros to make a
grouping of four digits:
0000 0000 1000 0000


We can do this in decimal notation to show why this can be done:
the number 0045 and 45 are the same number.
Now, convert the binary groupings into hexadecimal digits:
0000 0000 1000 0000"
0 0 8 0

Donc si on prend ton exemple Cirec :

<strike>1</strike>0000001 <strike>1</strike>0110001 <strike>1</strike>0110001 <strike>1</strike>0110001

On obtient  0000001   0110001   0110001   0110001

Il reste 0000001   0110001   0110001   0110001
On rajoute 4 zéros 0000 0000001   0110001   0110001   0110001

On obtient donc 00000000  00101100 01011000 10110001 et non  
10110001 0110001 0110001
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
8 mai 2008 à 05:33
ils sont virés automatiquement il me semble puisqu'il n'influent pas sur le résultat
10110001 0110001 0110001 2906289 $2C58B100000000  00101100 01011000 10110001 2906289 $2C58B1

 
@+
Cirec

<hr siz="" />
0
Utilisateur anonyme
8 mai 2008 à 06:26
La procédure de Kenavo me donne
10110001 01011000 00101100 00000000
Si on part de 10000001 10110001 10110001 10110001
Ca colle pas du tout
0
Utilisateur anonyme
8 mai 2008 à 06:45
J'ai fais un autre test
010110010001001000000000000000000 Devient
010110010000100100000000000000000

Je suis en Little Endian
0
Rejoignez-nous