IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> [RESOLU] Ré-écriture de fichiers MIDI, Si possible automatisée
Options
Anard
posté 25 Feb 2018, 13:20
Message #1


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



Bonjour,
J'ai une série de fichiers MIDI (plus de 200) à réécrire légèrement.
Le Format MIDI est écrit en hexa, pour faire simple (je passe les en-têtes), j'ai une première série d'octets indiquant un délai à attendre avant l'évènement suivant.
Ensuite arrive un octet de type d'évènement (0x80 à 0xFF). Pour les évènements concernant des notes, seul le bit de poids fort indique l'action, le second bit indique le canal MIDI.
Suivant l'évènement, le nombre d'octets à suivre est soit défini (entre 1 et 3), soit précisé par l'octet suivant.
Bref, ce qui m'intéresse particulièrement, ce sont les notes elles-mêmes. Elles sont écrites comme ceci :
  • Octet d'évènement :
    • 0x8c = fermer la note sur le canal c
    • 0x9c = ouvrir la note sur le canal c
  • Octet de hauteur de note : une valeur entre 0 et 127 (0x00 à 0xFF)
  • Octet de vélocité, correspondant à une force de frappe entre 0 et 100. Celui-ci ne m'intéresse pas.


Je cherche sur l'ensemble de mes fichiers à chercher toutes les notes du canal 0, et si la hauteur est inférieure à 54, la placer sur le canal 2 ; si la hauteur est inférieure à 66, la placer sur le canal 1 ; la laisser sur le canal 0 si la hauteur est supérieure ou égale à 66.
Dit comme ça, ça ne me parait pas bien compliqué.

J'ai commencé par faire un script dans HarmonyAssistant qui fait le boulot. Dans l'ensemble, ça fonctionne à peu près, sauf que Harmony gère mal le format MIDI, il préfèrerait des .mus. En fait un morceau sur deux est mal importé. Donc même si le script fait bien le travail, il part d'un fichier mal importé. Donc après export, mes MIDI ne correspondent plus du tout à la musique originale.
J'ai essayé MuseScore, qui abîme moins le fichier original lors de l'importation, mais qui l'abîme quand même. J'ai essayé également MidiSwing, qui semble mieux gérer l'import mais qui ne peut pas faire d'actions automatisée sur le fichier.

J'ai donc cherché à réaliser un programme qui réalise le travail directement sur le fichier en le lisant en hexa. Sauf que je ne sais pas faire ça sur ordi, alors j'ai programmé un µC (en C), en utilisant la bibliothèque FatFs.
Le programme ouvre le fichier (en lecture/ecriture) depuis une carte SD, enregistre avant chaque nouvel évènement le pointeur de l'endroit où il se trouve dans le fichier. S'il repère une ouverture ou fermeture de note sur le canal 0, il lit l'octet suivant pour connaître la hauteur de la note et si les conditions sont remplies, il revient en arrière au niveau de l'octet d'évènement et réécrit l'octet pour y mettre le bon canal (il écrit 0x81, 0x82, 0x91 ou 0x92 suivant le cas).
Ca fonctionne... pour la première note à modifier mad.gif Dès la deuxième écriture, il n'arrive pas à terminer son cycle d'écriture (il ne sort pas de la fonction f_write()) et le fichier devient inutilisable. Il doit y avoir quelque chose que je n'ai pas compris dans la fonction f_write() de la bibliothèque FatFS mais je ne vois pas du tout ce qui se passe.

Voilà, si quelqu'un a une idée de la méthode que je pourrai employer pour simplement modifier mes octets d'évènements en étant sûr de ne pas toucher au reste (contrairement aux logiciels d'édition de partitions), ça m'intéresse beaucoup.
Je n'ai jamais programmé en C sur ordinateur, mais je suis prêt à apprendre (ça ne doit pas trop changer par rapport aux µC). Si ça pouvait être fait par un simple script, ce serait peut-être plus simple mais j'ai bien du mal à trouver comment lire en hexa dans un fichier. Pour contrôler les modifs visuellement je n'ai trouvé que cette commande qui affiche le contenu du fichier en hexa dans le Terminal
Code
od -t x1 "nomDuFichier.mid"

Sinon, si vous avez une idée sur la raison qui empêche mon µC d'écrire à plusieurs reprises dans un même fichier, ça pourrait être encore la solution la plus facile pour moi...

Merci beaucoup pour votre aide.

Extrait de mon programme sur µC :
CODE
#define READ_BYTES ((f_read(&File, &buff, bytesToRead, &readedBytes) == FR_OK) && (readedBytes == bytesToRead))
#define WRITE_BYTES ((f_write(&File, &newEvent, 1, &readedBytes) == FR_OK) && (readedBytes == 1))

MIDI_RESULT Read_MIDI_Event(void)
{
// Lecture de la musique proprement dite
long buff = 0; // Buffer de sortie (initialisé pour être sûr qu'il ne reste rien dedans : sa taille est plus grande que les premières données à lire...))
unsigned int bytesToRead = 1;
unsigned int readedBytes;
char i, str[NB_COL+1];
unsigned char newEvent;

long pointer = File.fptr;
if (!READ_BYTES) return MID_TRUNCATE;

// Evènement précédent terminé, recherche du nouveau nombre de lectures
if (!readsToDo) {
// Nouveau Statut : on enregistre et on re-lit. Sinon, même évènement que précédent
if (buff & 0x80) {
Event = buff;
// Real-Time messages, octet seul qui ne nous intéresse pas
if (Event > 0xF0 && Event < 0xFF)
return MID_OK;

else if (Event == 0x80 || Event == 0x90) {
if (!READ_BYTES) return MID_TRUNCATE;
if (buff < 66) {
DataLED = 1;
if (f_lseek(&File, pointer) != FR_OK) return INVALID_FILE;
newEvent = Event & 0xF0;
if (buff < 54) newEvent = newEvent | 0x02;
else newEvent = newEvent | 0x01;
//if (f_putc(buff, &File) < 0) return WRITE_ERR;
if (!WRITE_BYTES) return WRITE_ERR;
if (!READ_BYTES) return MID_TRUNCATE;
DataLED = 0;
}
}

else // On lit le premier octet
if (!READ_BYTES) return MID_TRUNCATE;
}

// Meta-Event, on enregistre son type puis le nombre de lectures
if (Event == 0xFF) {
if (!buff) return INVALID_MIDI;
metaEvent = buff;
// puis lire le nombre de lectures
do {
if (!READ_BYTES) return MID_TRUNCATE;
readsToDo = readsToDo << 7;
readsToDo += (buff & 0x7F);
} while ((buff & 0x80) > 0);
if (readsToDo > 0) { // reads>0 pour éviter un "MID_TRUNCATE" : c'est le cas d'un évènement Fin de Piste qui a 0 bits à lire derrière
// On lit le premier octet
if (!READ_BYTES) return MID_TRUNCATE;
}
// On incrémente readsToDo s'il est nul pour pas qu'il ne se retrouve négatif en fin de lecture
else readsToDo++;
}

// System Exclusive, donne sa longueur par un byte de fin (0xF7)
else if (Event == 0xF0)
readsToDo = 1;

// DONNEES
else {
// ProgChange et CanalPressure n'ont qu'un byte à lire
if ((Event & 0xF0) == 0xC0 || (Event & 0xF0) == 0xD0)
readsToDo = 1;
else readsToDo = 2;
}
}

// Nombre de lectures enregistré, on traite l'octet lu et on décrémente readsToDo
// META-EVENT
if (Event == 0xFF && metaEvent == 0x2F)
{
// Fin de piste
nbPistes--;
if (!nbPistes) return MID_EOF;
else return Read_Track_Headers();
}
else if (Event == 0xF0) {
while (buff != 0xF7) {
if (!READ_BYTES) return MID_TRUNCATE;
}
readsToDo--;
return MID_OK;
}
else {
readsToDo--;
while (readsToDo) {
if (!READ_BYTES) return MID_TRUNCATE;
readsToDo--;
}
return MID_OK;
}
}


Ce message a été modifié par Anard - 1 Mar 2018, 15:38.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
Jaypee
posté 27 Feb 2018, 07:39
Message #2


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 399
Inscrit : 29 Aug 2002
Membre no 3 340



Question naïve...
Est-il possible de lire la totalité du fichier midi en mémoire, puis de travailler seulement en mémoire?
Puis de réécrire la mémoire vers un nouveau fichier?
J-P
PS: Y'a des ressources en C++ dans GitHub pour la programmation MIDI:
https://github.com/craigsapp/midifile
En Python également, qui a mon sens, est la meilleure option :
https://github.com/vishnubob/python-midi ou https://github.com/olemb/mido

Ce message a été modifié par Jaypee - 27 Feb 2018, 15:03.
Go to the top of the page
 
+Quote Post
Anard
posté 27 Feb 2018, 15:03
Message #3


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



Bonjour et merci pour cette réponse.
Charger l'ensemble du fichier en mémoire, ça me parait tendu : le µContrôleur que j'utilise n'a que 4k de RAM…

En revanche, j'ai téléchargé la dernière version de FatFS et je travaille sur 2 fichiers.
Un en lecture seule et un que je crée à l'ouverture du premier en écriture seule.
Je lis le premier octet par octet et écrit ce que j'ai lu dans le nouveau fichier dans la foulée. Si je repère les conditions pour modifier le canal MIDI, au lieu d'écrire ce que j'ai lu dans le premier fichier, j'adapte ce que je dois écrire dans le second. Je simplifie, en vrai il y a quelques autres choses à faire attention, mais en gros c'est ça.

Pour le moment, j'ai fait un essai sur un fichier en mode "Debug". C'est à dire que l'ordi est connecté à ma puce et que je peut faire des pauses dans l'execution du programme pour voir si tout se passe bien. Ca a eu l'air de bien se passer, sauf que le fichier a été un peu trop modifié au final (par exemple, des notes qui s'ouvrent et oublient de se fermer). Je ne sais pas si ça fonctionnera mieux si je ne fais pas de pause au cours de l'écriture.
J'ai donc programmé ma puce pour lancer le programme de manière autonome. Ca va très doucement (5 à 10 minutes par fichier), mon logiciel ne doit pas être super optimisé, mais je verrai ce que ça donne au bout de 2 ou 3 fichiers.

J'ai regardé tes liens, mais c'est des languages que je n'ai pour le moment jamais étudiés… J'y reviendrai si je galère trop.

Ce message a été modifié par Anard - 1 Mar 2018, 16:04.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
Anard
posté 27 Feb 2018, 16:24
Message #4


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



Petite erreur de ma part pour les notes qui ne s'éteignaient pas. Ca a l'air de marcher, je vais lancer la conversion. Mais ça change d'un ordi une puce qui tourne à 4MHz. Il va y passer la nuit ! laugh.gif

J'avoue que c'est un peu débile mon système. mais déjà, le fait d'éditer le fichier directement en hexa me permet d'être sûr qu'un logiciel quelconque n'aura touché à rien d'autre. Et autant, j'arrive à lire et écrire sur une carte SD, en FAT, avec un µC, autant lire et écrire sur le disque de mon ordinateur, ça risquerait de me demander un (long?) temps d'apprentissage …

Ce message a été modifié par Anard - 27 Feb 2018, 19:19.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
Jaypee
posté 27 Feb 2018, 19:59
Message #5


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 399
Inscrit : 29 Aug 2002
Membre no 3 340



Tu dois pouvoir améliorer un poil les temps de traitement en diminuant la lecture disque. Je m'explique: Lire un byte ou en lire 32 ou 64 à la fois, coûte à peu près autant. Donc avec une lecture byte par byte côté traitement mais 32 par 32 ou 64 par 64 côté fichier. Il faut une fonction getByte() qui soit avance le pointeur de 0 à 31 ou 0 à 63, soit arrive au bout du tampon et relit une nouvelle fournée et renvoie le premier byte. Celà diminue de 32x ou 64x les accès disque qui sont lents.
On initialise le pointeur en le plaçant directement à la fin du tampon pour commencer, ce qui forcera une lecture disque.

@+JP
Go to the top of the page
 
+Quote Post
Anard
posté 27 Feb 2018, 20:06
Message #6


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



En effet, merci du conseil.
Je ne sais pas si je vais prendre le temps de faire la correction, parce qu'il commence à être tard et d'ici demain matin, il devrait avoir terminé son taf sans que je n'aie retouché à rien.
Ca me paraissait plus compliqué à cause du fait de passer par un buffer, mais tu as raison c'est absurde.
D'autant qu'en SPI (quand je parle avec la carte), je suis limité à 4MHz pour que les choses se passent bien, mais le µC, s'il ne fait que du traitement peut tourner à 64MHz wink.gif
Si demain, je me rends compte qu'il y a des erreurs de conversion (je n'espère pas unsure.gif ), j'en profiterai pour mettre ça en place.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
Anard
posté 28 Feb 2018, 10:04
Message #7


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



J'ai jeté un œil (mon programme s'est arrêté au premier changement de dossier...) mais en fait je crois qu'il faut que je lise tout mon buffer à l'envers.
En effet, par exemple quand je lis l'en-tête d'un fichier par exemple. Je lisais déjà 4 octets "d'un coup".
Code
f_read(&File, &buff, 4, &readedBytes)

Et bien l'en-tête d'un fichier MIDI est 0x4D546864 et je retrouve dans mon buff : 0x6468544D

D'abord est-ce que la fonction f_read fonctionne toujours comme ça à retourner le résultat attendu (en tout cas attendu par moi tongue.gif ) ou est-ce spécifique à mon compilateur (XC8 sur MPLab) ?
Si je lis 64 octets d'un coup par exemple, j'aurai donc un tableau BUFF[64], j'enregistre readedBytes pour savoir jusqu'où il a été écrit.
Et je relis tout à l'envers, c'est ça ?
Code
error = f_read(&File, &BUFF, 64, &readedBytes);
if (!readedBytes) return error;
// lecture octet par octet
writedBytes = 0;
octet = BUFF[readedBytes];
while (readedBytes) {
    // effacer l'octet lu
    BUFF[readedBytes] = 0;
    readedBytes--;
    writedBytes++;
    // traitement (remplir OutBUFF à l'envers aussi pour la réécriture du fichier)
    // ----------------
    // suivant
    octet = BUFF[readedBytes];
}
error = f_write(&FileWrite, &OutBUFF, writedBytes, &readedBytes);
return error;


Ce serait un truc comme ça ? Si c'est ça, il faut que je voies comment écrire le buffer de sortie car suivant la situation, je rajoutes des octets dans le fichier à écrire.
En effet, la norme MIDI utilise ce qu'ils appellent le RunningStatus :
S'il y a plusieurs évènements identiques à suivre, l'octet d'évènement n'est pas répété par exemple pour ouvrir 2 notes en même temps, on aura :
  • octet(s) de délai
  • 0x90 (ouverture de note sur le canal 0) - hauteur de note - velocite
  • octet(s) de délai
  • hauteur de note - velocite
  • ...

Si dans ces différentes notes, l'une d'elle ne doit pas être inscrite sur le même canal que le précédent, je suis obligé d'insérer un octet d'évènement :
  • octet(s) de délai
  • 0x90 (ouverture de note sur le canal 0) - hauteur de note - velocite
  • octet(s) de délai
  • 0x91 (ouverture de note sur le canal 1) - hauteur de note - velocite
  • ...

Donc mon buffer de sortie sera plus gros que mon buffer d'entrée, mais je ne sais pas de combien avant d'avoir traité les octets.

PS : il y a eu un souci lors de l'écriture de mon message, le début a été écrit deux fois, mais je n'arrive pas à éditer le prmier message, si un modo veut le supprimer, il est bienvenu jap.gif

Ce message a été modifié par Anard - 28 Feb 2018, 10:40.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
osnola
posté 28 Feb 2018, 14:15
Message #8


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 1 565
Inscrit : 21 Sep 2004
Lieu : Nancy
Membre no 23 949



Bonjour,
Citation (Anard @ 28 Feb 2018, 10:04) *
J'ai jeté un œil (mon programme s'est arrêté au premier changement de dossier...) mais en fait je crois qu'il faut que je lise tout mon buffer à l'envers.
En effet, par exemple quand je lis l'en-tête d'un fichier par exemple. Je lisais déjà 4 octets "d'un coup".
Code
f_read(&File, &buff, 4, &readedBytes)

Et bien l'en-tête d'un fichier MIDI est 0x4D546864 et je retrouve dans mon buff : 0x6468544D

Normalement, tu devrais retrouver 4D 54 68 64 dans buff, ie. si buff est un char *, tu peux vérifier que buff[0]=0x4d, ..

Par contre si tu considères que buff est un entier, dans un système en little endian ( voir https://fr.wikipedia.org/wiki/Endianness ), les entiers sont écrits à l'envers, ie. l'entier 0x6468544D est stocké est mémoire sous la forme 4d 54 67 64...
Go to the top of the page
 
+Quote Post
Jaypee
posté 28 Feb 2018, 20:10
Message #9


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 399
Inscrit : 29 Aug 2002
Membre no 3 340



Je suprime mon message dupliqué et non formatté...

Ce message a été modifié par Jaypee - 1 Mar 2018, 08:08.
Go to the top of the page
 
+Quote Post
Jaypee
posté 28 Feb 2018, 20:34
Message #10


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 399
Inscrit : 29 Aug 2002
Membre no 3 340



Concernant la navigations des dossiers et des fichiers :
Il faut séparer les problèmes (avec un "pattern visiteur" = fonction parcours + fonction visite),
- faire un programme qui énumère les fichiers (genre commande "find" du bash), d'une part et
- faire le filtre qui transforme un fichier MIDI, un seul.

Concernant le typage du tampon:
Il faut un type byte. S'il n'existe pas

typedef unsigned char byte

fait le job. Et le tampon est un tableau statique de byte

Code
byte buffer[4]; // Il faut probablement aligner avec la longueur du mot machine, 4 si 32 bits 8 si 64 bits.
int index = sizeof(buffer) - 1;

byte function getByte() {
    index += 1;
    if (index >= sizeof(buffer) {
         fread d'un nouveau buffer
         index = 0;
    }
    return buffer[index];
}


On peut avoir le même schéma pour le fwrite avec une void function putByte(); qui ajoute dans le buffer de sortie, mais lorsque l'index atteint la fin, on vide le buffer de sortie dans le fichier de sortie et on remet l'index au début.

Dans un style plus sophistiqué on pourrait créer une sorte de fprintf avec un format %1B ou %2B pour écrire exactement le nombre de bytes voulu. J'ai dû une fois écrire des bandes magnétiques pour une machine 36 bits, et j'ai dû écrire ce genre de fonction.
J-P

Ce message a été modifié par Jaypee - 1 Mar 2018, 08:14.
Go to the top of the page
 
+Quote Post
Anard
posté 1 Mar 2018, 11:16
Message #11


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



Pour la navigation dans les dossiers, je pense avoir trouvé. La librairie FatFs que j'utilise propose le format FILINFO qui donne les infos sur le fichier pointé. J'en utilise donc 1 qui point sur le dossier avant que je ne l'ouvre et un second qui pointe sur le fichier sur lequel je travaille. Comme ça, quand je ferme le fichier et que j'ai atteint la fin du dossier, je referme le dossier et parcours le dossierr parent jusqu'à retrouver le dossier pointé par mon premier FILINFO (pour ma conversion, je n'utilise pas de sous-sous-dossiers.

En revanche, j'ai encore quelques soucis, qui devraient être réglés ce soir j'espère. C4est surtout au moment de la mise à jour des buffers de lecture et d'écriture. En effet, dans mes conversion, j'ai quelque fois besoin d'aller voir la valeur suivante/précédente. Si les buffers ont été mis à jour entre temps, ces valeurs n'existent plus. Il faut juste que j'arrive à gérer ça. Et en effet, j'ai fait des essais sur quelques fichiers, ça change de manière impressionnante le temps de traitement de travailler avec cette méthode (si j'en viens à bout). En plus, le µC dispose d'une option PLL qui multiplie sa fréquence de travail par 4. Je passerai donc de 16 à 64MHz quand je ne travaille pas directement sur la carte SD (qui elle est toujours limitée à 4MHz).

A suivre…

EDIT : Bien, la conversion est lancée. J'ai même rajouté un petit truc : à l'ouverture d'un dossier, il crée un fichier result.log et dès qu'il ouvre un fichier, il y inscrit "Fichier.fname: " puis quand il le ferme il rajoute "OK\r\n" si ça s'est bien passé et "ERREUR: numeroDeLErreur\r\n" sinon.
Ca me permettra de contrôler les éventuelles erreurs rencontrées sans avoir à rester devant wink.gif

IMPECCABLE, moins d'une minute par morceau maintenant ! Merci beaucoup pour votre aide jap.gif

Ce message a été modifié par Anard - 1 Mar 2018, 16:02.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
Anard
posté 1 Mar 2018, 21:05
Message #12


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 592
Inscrit : 7 May 2015
Membre no 195 224



Citation (osnola @ 28 Feb 2018, 14:15) *
Bonjour,
Citation (Anard @ 28 Feb 2018, 10:04) *
J'ai jeté un œil (mon programme s'est arrêté au premier changement de dossier...) mais en fait je crois qu'il faut que je lise tout mon buffer à l'envers.
En effet, par exemple quand je lis l'en-tête d'un fichier par exemple. Je lisais déjà 4 octets "d'un coup".
Code
f_read(&File, &buff, 4, &readedBytes)

Et bien l'en-tête d'un fichier MIDI est 0x4D546864 et je retrouve dans mon buff : 0x6468544D

Normalement, tu devrais retrouver 4D 54 68 64 dans buff, ie. si buff est un char *, tu peux vérifier que buff[0]=0x4d, ..

Par contre si tu considères que buff est un entier, dans un système en little endian ( voir https://fr.wikipedia.org/wiki/Endianness ), les entiers sont écrits à l'envers, ie. l'entier 0x6468544D est stocké est mémoire sous la forme 4d 54 67 64...


J'avoue que ça reste obscur pour moi cette histoire. Enfin, je me suis adapté en fonction.
Mais en effet, quand je fais
Code
f_read(&File, &buffer, 4, &readedBytes);

J'ai 0x6468544D dans buffer. En revanche, si je lis buffer[0], buffer[1], buffer[2] puis buffer[3], j'ai bien 4D, 54, 68 puis 64. Ca doit être que les octets de poids fort sont à gauche.
Quand je fais
Code
f_write(&File, &buffer, 4, &writedBytes);

J'écris bien dans le bon ordre. En revanche, à un moment, je dois inscrire la longueur (en octets) de la piste (dans son header), que j'ai rallongée dans l'opération. Au fur et à mesure de l'écriture, j'incrémente un unsigned long octetsEcrits (octetsEcrits++) et quand la piste est terminée, je reviens au début inscrire la bonne longueur au bon endroit. Eh bien là, je dois retourner mes 4 octets avant le f_write, sinon, c'est écrit à l'envers (0x00002467 devient 0x67240000).

Ce message a été modifié par Anard - 1 Mar 2018, 21:06.


--------------------
"iMack" : GA-H97M-D3H, Intel i5 4460, 16Go DDR3, Asus GTX670, SSD 128+120+60Go, HDD 500Go+2To / Clover - macOS Mojave / Ubuntu Bionic Beaver / Windows 10
"Portable" : Samsung P200, Intel Core2Duo T8100, 3Go DDR2, Radeon X1250, HDD 160Go / Grub2 - SliTaz 5.0 rolling / Windows 10
Go to the top of the page
 
+Quote Post
mpergand
posté 2 Mar 2018, 02:18
Message #13


Macbidouilleur de vermeil !
****

Groupe : Membres
Messages : 1 198
Inscrit : 8 Oct 2003
Membre no 10 220



Salut,

Il faut que tu convertisses en big endian à la sauvegarde.

Un peu de lecture:
Endian independent code

Le plus simple c'est d'utiliser les fonctions htons ntohs si la lib est dispo pour toi.

Sinon faire une petite routine:
Code
short swapShort(short v)
{
    short r;    // valeur de v inversée
    char *in=(char*)&v;
    char *out=(char*)&r;

    out[0]=in[1];
    out[1]=in[0];

    return r;
}


Tu dois faire le swap à la lecture du fichier
et une nouvelle fois à l'écriture dans le fichier.

Pour les ints 32 bits, Je te laisses faire la routine toi même wink.gif
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 11th December 2019 - 21:44