Partage
  • Partager sur Facebook
  • Partager sur Twitter

[résolu] f.seekp(5, std::ios::beg);

Créer le poids d'un fichier audio

    9 mai 2024 à 15:25:49

    Bonjour,

    Depuis presque deux semaines j'essaie désespérément de modifier le poids des fichiers audio que je génère.

    Je n'y arrive pas, est-ce que quelqu'un peu m'aider ?

    voici mon code :

    		f.seekp(0, std::ios::end);  //je me mets à la fin du fichier audio
    		int ou = f.tellp();//je récupère le poids du fichier	
    		f.clear();
    				f.seekp(5, std::ios::beg);// je place le curseur à la première adresse du poids du fichier le 5,6,7,8
    		f<< "0x" << std::setfill('0') << std::setw(2) << std::hex << ou;
    		f.seekp(41, std::ios::beg);//je place le curseur à la deuxième adresse à modifier 41,42,43,44
    		f<< "0x" << std::setfill('0') << std::setw(2) << std::hex << ou;

    c'est dans une fonction que j'ouvre comme ça

    std::string const f1("audiojo.wav");
    std::ofstream f (f1.c_str(), std::ios::binary | std::ios::app | std::ios::in | std::ios::out | std::ios::ate);
    	if(!f) {

    et mes includes sont

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <array>
    #include <bits/stdc++.h>
    #include <fstream>
    #include <string>
    #include <iomanip>
    #include <stdio.h>
    //#include <format>
    #include <sstream>



    Le résultat controler avec ghex est que j'écris à la fin et non pas aux positions indiquées

    -
    Edité par pierrejocelynleonraoulandre 9 mai 2024 à 22:49:43

    • Partager sur Facebook
    • Partager sur Twitter
      9 mai 2024 à 15:38:14

      Donc... Tu ouvres un fichier qui est censé être en binaire (le .wav est pas un format texte), tu écris du texte dedans, et tu t'étonnes que ça fasse pas ce à quoi tu t'attends ?

      EDIT:

      Le plus rigolo, c'est que tu l'ouvres bien avec std::ios::binary

      -
      Edité par dragonjoker 9 mai 2024 à 15:39:07

      • Partager sur Facebook
      • Partager sur Twitter

      Si vous ne trouvez plus rien, cherchez autre chose.

        9 mai 2024 à 16:26:00

        Bonjour, merci pour la réponse.

        Avez-vous une proposition de solution ?

        Concernant la conversion en binaire avant, il y avait format, mais cette technique de conversion n'est plus en c++, c'est pourquoi j'utilise :

        f<< "0x" << std::setfill('0') << std::setw(2) << std::hex << ou;

        Le role de cette ligne de code est de convertir en premier en hexa, puis d'ajouter l'écriture au bon format wav du fichier avec le 2x0 devant

        A aucun moment j'ai essayer d'écrire un int comme imaginé, de toute façon, le problème est que je n'écris pas à la bonne adresse, ce n'est pas l'écriture dans un mauvais format.

        -
        Edité par pierrejocelynleonraoulandre 9 mai 2024 à 16:29:30

        • Partager sur Facebook
        • Partager sur Twitter
          9 mai 2024 à 17:08:22

          Ecris des octets dedans (avec ofstream::write). Pas du texte (<<)

          Et "0x02" c'est du texte. Contrairement à 0x02, encore égal à 2, 002, 0b00000010...

          -
          Edité par lmghs 9 mai 2024 à 17:09:19

          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            9 mai 2024 à 19:37:56

            Merci pour la réponse concernant la technique pour écrire les exa, mais actuellement mon problème c'est que j'écris à la fin du fichier avec f.seekp.

            Je vais étudier comment fonctionne ofstream::write

            Mais sincèrement j'ai des doutes sur vos affirmations.

            J'ai créé une application qui génère des fichiers audio, elle fonctionne très bien, il ne me manque qu'à modifier le poids car actuellement j'utilise un poids lourd pour éviter que le fichier audio soit coupé. et j'utilise cette technique (<<)

            De vous donner cette précision, me fait penser à une autre solution possible pour l'écriture, mon problème reste le positionnement.

            Est-ce que quelqu'un peut répondre à la question sans tenir compte de ma manière d'écrire les exa ?

            Cordialement

            -
            Edité par pierrejocelynleonraoulandre 9 mai 2024 à 20:22:35

            • Partager sur Facebook
            • Partager sur Twitter
              9 mai 2024 à 20:11:49

              Parce que tu ouvres ton fichier avec `std::ios::app`

              > seek to the end of stream before each write

              https://en.cppreference.com/w/cpp/io/ios_base/openmode

              -
              Edité par jo_link_noir 9 mai 2024 à 20:13:01

              • Partager sur Facebook
              • Partager sur Twitter
                9 mai 2024 à 21:24:31

                Merci pour la réponse, si c'est l'origine du problème, je vais changer de technique et fermé l'appli pour  ajouter une appli qui corrigera l'entête du fichier ou carrément écrira l'entête entière à la fin. Je suis obligé d'utiliser cette fonction, car l'application ajoute à la demande le nombre de formes acoustiques.

                Si cela fonctionne je reviendrais mettre en résolu

                En détail si cela intéresse, mon appli pour compositeur est composé d'une appli qui crée des formes en format texte, puis d'une appli qui transforme ces formes dans un fichier wav, il me suffit d'ajouter l'appli qui corrige l'entête après. Dès que j'ai fini j'injecte dans le git du projet

                Cordialement

                -
                Edité par pierrejocelynleonraoulandre 9 mai 2024 à 21:31:23

                • Partager sur Facebook
                • Partager sur Twitter
                  10 mai 2024 à 23:18:23

                  Et voila le code qui va bien pour info :

                  	if(!f) {
                  		std::cerr << "Impossible d'ouvrir le fichier en écriture !" << std::endl;
                  		//return 1;
                  	}
                      f.seekp(0, std::ios::end);  //je me mets à la fin du fichier audio 
                   
                    
                      int poids = f.tellp();//je récupère le poids du fichier
                               
                              if (poids > (65536) )
                              {
                              int a,b,c,d,k=0,j=0;
                              a = poids % (256);            
                              for (int i = 0; i < poids; i=i+65536) {  k++;}
                              c=k-1;
                              d =  poids % (65536);
                              for (int i = 0; i < d; i=i+256) {  j++;}
                              b=j-1;
                              f.seekp(4, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[a];
                              f.seekp(5, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[b];
                              f.seekp(6, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[c];
                              f.seekp(40, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[a];
                              f.seekp(41, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[b];
                              f.seekp(42, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[c];
                              }
                              if (poids < 65536)
                              {
                              int a,b,j=0;
                              a= poids % (256);
                              for (int i = 0; i < poids; i=i+256) {  j++;}
                              b=j-1;
                              f.seekp(4, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[a];
                              f.seekp(5, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[b];
                              f.seekp(40, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[a];
                              f.seekp(41, std::ios::beg);//je me place ou il faut remplacer
                              f<<tabn[b];
                               for (int i = 0; i < poids; i=i+256) {  j++;}
                               b=j;
                              }
                  
                      f.close();
                    }          
                  

                  C'est poussé dans le git du projet

                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 mai 2024 à 0:23:57

                    Je ne vois pas comment cela pourrait bien fonctionner avec des variables non initialisées. Tu devrais vraiment configurer ton compilateur.

                    De plus, tu utilises les API type texte qui font plus que simplement écrire ce qui est demandé. Comme l'a dit @lmghs, tu devrais utiliser write() ce qui donne

                    char data[] { /*mettre les octets à écrire ici*/ };
                    f.write(data, sizeof(data));
                    

                    Au passage, std::filesystem::file_size donne la taille du fichier. Il n'est pas nécessaire de déplacer le curseur avec seekp à chaque fois: il avance du nombre d'octet écrit.

                    for (int i = 0; i &lt; poids; i=i+256) { j++;} -> j += poids / 256;

                    Ton code est très mal indenté.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      11 mai 2024 à 8:03:10

                      Mille mercis pour les précieuses informations, je vais regarder plus au moment.

                      En détail si cela intéresse. le code fonctionne très bien, il est donné en entier dans le GIT

                      En 1993 j'ai créé mon propre système mathématique construit sur l'idée que chaque évènement possédait sa base de temps, ceci afin de pouvoir exercer mon métier de régleur. De manière à prouver la puissance de l'outil, j'ai créé bien plus tard un générateur vidéo en javascript. Depuis peu à la retraite, je viens de finir de créer une appli qui permet de composer de la musique, voix humaine compris. Ce générateur est construit sur un format audio ultra léger que j'ai créé. Pour que celui-ci soit compréhensible, j'ai utilisé un format texte, ou chaque onde est représenté par 4 valeurs.

                      Par habitude, j'écris tout directement avec un éditeur texte (à un moment vi ), cela me permet de garder le contrôle sur les associations d'idées.

                      Avant de commencer à ajuster les indentations et améliorer les codes je dois

                      Finir d'injecter les générateurs de fichiers en format texte sur le GIT

                      Ensuite, je dois expliquer comment fonctionne l'outil pour les compositeurs

                      ensuite, je dois largement commenter le code pour expliquer ce que je fais,

                      et à la fin, je m'occupera de mettre aux noremes les indentations.

                      Cordialement

                      -
                      Edité par pierrejocelynleonraoulandre 11 mai 2024 à 8:06:21

                      • Partager sur Facebook
                      • Partager sur Twitter
                        11 mai 2024 à 14:15:34

                        Je rajouterai qu'il est préférable d'utiliser des fonctions de type host_to_network (format network =~big endian) (ou host to little?) pour convertir des nombres en représentation interne (host) vers le format attendu (en général, le format big endian est le plus courant en réseau ou dans des fichiers -- pour diverses raisons historiques techniques et humaines).

                        Pourquoi ces fonctions? Beaucoup plus clair (une fonction bien nommée qui factorise un boulot qui obscurcirait localement le code autrement), et efficace (pas de conversion ni de triturage d'ordre s'il est détecté que le nombre est stocké en interne dans le même format que celui dans lequel il sera écrit).

                        Seul hic, d'une machine à l'autre POSIX (https://man7.org/linux/man-pages/man3/endian.3.html) ou windows, ce ne sont pas les mêmes noms... Après quelqu'un s'est amusé à produire une version portable: https://gist.github.com/panzi/6856583 (manquerait juste une version C++ qui fournit un seul nom surchargé et c'est le bonheur!)

                        • Partager sur Facebook
                        • Partager sur Twitter
                        C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                          12 mai 2024 à 11:55:41

                          Bonjour,

                          Il faut tenir compte de l'historique.

                          Les évènements font que j'ai choisit un format léger 8bits (seulement 256 positions,) pour montrer les lois physiques, c'est directement issus des jeunes druides qui tiraient la branche du chêne pour montrer l'hystérésis, et qui est resté dans notre manière d'agencer les idées. Il se trouve que c'est du little endian.

                          Comme ce qui nous rend humain, est la création, j'ai apporté un outil pour pouvoir créer, faire de l'art, découvrir, je suis entrain de mettre sur la page des captures d'écran en ajustant les sonorités de démo.

                          Le tout est sur un GIT, chacun peut créer sa branche en respectant la licence GNU, pour moi une fois les explications et les indentations finies, je regarderai un format audio du libre, mais rien n'empêche que chacun adapte pour une utilisation qui lui va, comme créer son propre instrument de musique piloter avec des rayons lumineux, ou encore mieux des focales qui reprenne l'analogique , les équilibres des lois qu'apporte l'outil ici présenté.

                          En d'autres mots, oui c'est important, mais je ne suis qu'une feuille porté par le vent et le sol est trop proche pour que j'envisage de long trajets.

                          Cordialement

                          • Partager sur Facebook
                          • Partager sur Twitter
                            15 mai 2024 à 21:11:00

                            Bonjour,

                            Pour ceux que ça intéresse pour tester, l'archive complète est là https://www.letime.net/son/ap/audiojo.tar.gz

                            L'application permet de transmettre des compositions musicales de quelques octets sous mon format qui génère des Mo en ogg stéréo

                            Chaque compositeur peut créer ses formes particulière en créant son propre générateur texte ou même directement avec un tableur, ou plus simplement utiliser un des générateurs déjà fourni.

                            Sur le git, il est possible de faire un fork car ma spécialité, c'est régleur, phénomènes physiques, technologies pour les utiliser, et langage machine avec goto, pas vraiment le c++

                            Cordialement

                            • Partager sur Facebook
                            • Partager sur Twitter
                              16 mai 2024 à 21:14:25

                              Bonjour, comme dit, j'ai relu et cherché à comprendre la proposition de "lmghs" .

                              J'ai hésité à répondre mais je pense devoir le faire car je pense que le vital, l'essentielle de ma démarche n'est pas entendue.

                              Je suis persuadé qu'un anglo-saxon, un arabe ou même un chinois ne peut pas comprendre ce que je fais, car son langage ne lui permet pas d'associer les idées à la française. Associer les idées à la française, c'est parler français, c'est percevoir le monde avec des concepts. Le format audio que je présente, ce sont des formes particulières qui suivent les lois physiques, quand j'écris un nombre, ce n'est pas un notion de quantité, ce n'est pas la de manière de l'écrire (big endian), ce n'est un adressage, ce n'est pas ..., quand j'écris un nombre c'est un symbole qui représente un concept qui permet de produire une forme sonore particulière. Parler à la française, c'est utiliser une étincelle, qui change de forme à chaque dimension qu'elle traverse pour allumer le feu qui réchauffe notre coeur. Il n'y a pas de compression, il n'y a pas de conversion. Il y a un faible souffle qui augmente en traversant les régions et les lois physiques pour s'appeler Mistral. Mon fauteuil est la culture française descendante des celtes, et mon coussin sont les encyclopédies descendants de 1789. Comprenez que c'est l'homme qui s'adapte à son environnement et comme l'a déjà fait windows en abandonnant 98 (le seul vrai windows) cet O.S. s'adaptera en copiant à nouveau pour survivre. Je ne peux, ni ne veux aller contre cette évidence.

                              Cordialement

                              • Partager sur Facebook
                              • Partager sur Twitter
                                17 mai 2024 à 1:37:02

                                Bonsoir,
                                Je pourrais parler aussi de métier VS technique. Le métier peut être hyper compliqué. Très bien. Jusqu'à un moment où "j'ai une information que je veux encoder d'une certaine façon". Là, les petites mains de la technique que nous sommes, on comprend bien mieux ce que les gens du métier imaginent.

                                Et on ne parle que de ça. Le reste, je ne juge pas et cela ne m'intéresse pas.

                                A voir le code final (?) où je vois un nombre qui est décomposé à la main en octets qui sont ensuite écrits à la queue leu-leu. Je vois un code inutilement alambiqué quand on connait ce que le langage et les pratiques nous offrent.

                                Le pourquoi? Le comment? Ce ne m’intéresse pas. Je vois un code informatique, et je fais des propositions de simplifications pour une maintenance future. On peut prendre ou ignorer.

                                Après j'avoue avoir fait un peu d'interprétation faute de vision de ce qu'est tabn[]. En m'appuyant sur https://fr.wikipedia.org/wiki/Waveform_Audio_File_Format#En-t%C3%AAte_de_fichier_WAV j'en déduis qu'en positions 4-7 on stocke la taille - 8 en little endian.

                                Soit

                                // uint32_t est pile le bon type exact à employer pour stocker des entiers non signés de taille 4
                                std::uint32_t size = ... tellg/std::filesystem::file_size(filename) qui va bien - 8;
                                // en vrai il faudrait vérifier que la taille tient bien sur 32 bits
                                
                                f.seekp(4, std::ios::beg); 
                                auto encoded_size = host_to_little(size);
                                f.write(reinterpet_cast<char const*>(&encoded_size), sizeof(encoded_size));


                                avec dans ma boite à outils host_to_little() qui est une surcharge des fonctions host_to_little pour les formats unsigned_int 16, 32 et 64 bits.

                                Si maintenant tabn[] ne correspond pas à l'information de taille à mettre en position 4 comme renseigné dans le format sur wikipédia. Au temps pour moi.

                                PS: EDIT: Faux, je disais une bêtise:  <<<"f << char(13 ou  10)" ça va vraiment faire n'importe quoi. Ou pourquoi il faut utiliser write!>>>
                                binary nous protège à priori. Au temps pour moi

                                PPS: les boucles i = 0 à taille en pas de N, ca se réécrit "taille > 0 ? (taille-1) / N +1 : 0". Plus besoin d'enlever le 1 à la fin avec la formule mathématique. Par contre, attention au cas 0. On sent que si d est nul et que l'on fait -1 après on va avoir des soucis. Je fais le pari de la doc, et que c'est bien la taille - 8 en little endian que l'on veut, et que du coup, la version simplifiée sera bien plus simple et exempte de bug.

                                EDIT2: je ne dis pas que la solution que je propose est une évidence. Elle est plus un kata/réflexe conditionné/gamme-de-solfège chez les initiés habitués à manipuler des formats de données "binaires".

                                -
                                Edité par lmghs 17 mai 2024 à 12:19:56

                                • Partager sur Facebook
                                • Partager sur Twitter
                                C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                  18 mai 2024 à 8:48:30

                                  @pierrejocelynleonraoulandre

                                  Je m'intéresse à ce qui touche au son et à la musqiue.

                                  J'ai réussi à compiler tes sources. Mais l'utilisation est un peu obscure. Que faut-il faire après ? Qu'est-ce que ton logiciel est censé produire exactement ?

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  [résolu] f.seekp(5, std::ios::beg);

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  • Editeur
                                  • Markdown