Partage
  • Partager sur Facebook
  • Partager sur Twitter

Peut-on "mélanger" C et C++ ?

p.e.: TP spectre [C] + demande de fichier [C++]

    1 juin 2008 à 21:41:20

    Bonjour, je suis le tutoriel pour apprendre à programmer en C++ de Mateo. J'en suis au point où on apprend à appeler des fenêtres pour demander un fichier à l'utilisateur (QFileDialog::GetOpenFileName et celui que je souhaite utiliser dans mon programme).

    Mon programm devra demander à l'utilisateur de choisir une chanson, puis, il la jouera avec le visualisateur spectrale du son (TP de la partie III du tutoriel C). Ce n'est qu'un début, mais j'améliorerai tout cela après.

    Ma question est donc, peut-on créer la fenêtre de demande de fichier, transformer l'adresse obtenue en chaîne de craractères, et envoyer cette adresse à la fonction visualisation?

    Mon code est pour l'instant copié à celui de Mateo, car je ne trouvais plus le main.c.

    Mon compilateur me dit que la déclaration de la fonction visualisation est mauvaise.

    Main.cpp
    #include <QApplication>
    #include <QTranslator>
    #include <QLocale>
    #include <QLibraryInfo>
    #include <QFileDialog>
    #include <QString>
    
    #include "Visualisation.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        QString locale = QLocale::system().name();
        QTranslator translator;
        translator.load(QString("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
        app.installTranslator(&translator);
    
        QString chemin = QFileDialog::getOpenFileName(NULL, "Selectionnez une chanson", "", "Musiques (*.mp3)");
        const char* fichier = chemin.toStdString().c_str();
    
        visualisation(fichier);
    
        return app.exec();
    }
    


    visualisation.h
    #ifndef VISUALISATION_H_INCLUDED
    #define VISUALISATION_H_INCLUDED
    
    int visualisation(const char *chemin);
    
    void setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
    
    #endif // VISUALISATION_H_INCLUDED
    


    visualisation.c
    #include <stdlib.h>
    #include <stdio.h>
    #include <SDL/SDL.h>
    #include <SDL/SDL_ttf.h>
    #include <FMOD/fmod.h>
    
    #define LARGEUR_FENETRE         512 /* DOIT rester à 512 impérativement car il y a 512 barres (correspondant aux 512 floats) */
    #define HAUTEUR_FENETRE         400 /* Vous pouvez la faire varier celle-là par contre :o) */
    #define RATIO                   (HAUTEUR_FENETRE / 255.0)
    #define DELAI_RAFRAICHISSEMENT  25 /* Temps en ms entre chaque mise à jour du graphe. 25 ms est la valeur minimale. */
    
    void setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
    
    int visualisation(const char *chemin)
    {
        SDL_Event event;
        SDL_Rect position;
        int continuer = 1, hauteurBarre = 0, tempsActuel = 0, tempsPrecedent = 0, i = 0, j = 0;
        int fini = 0;
        float *spectre = NULL;
    
        /* Initialisation de FMOD
           ----------------------
    
        On charge FMOD, la musique, on active le module DSP et on lance la lecture
        de la musique */
    
        TTF_Init();
        FSOUND_Init(44100, 4, 0);
        FSOUND_STREAM* musique = FSOUND_Stream_Open(chemin, 1, 0, 0);
        if (musique == NULL)
        {
            fprintf(stderr, "Impossible d'ouvrir la musique");
            exit(EXIT_FAILURE);
        }
        FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), 1);
    
        /* Initialisation de la SDL
           ------------------------
    
        On charge la SDL, on ouvre la fenêtre et on écrit dans sa barre de titre.
        On récupère au passage un pointeur vers la surface ecran, qui sera la seule
        surface utilisée dans ce programme */
    
        SDL_Init(SDL_INIT_VIDEO);
        ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_SWSURFACE | SDL_DOUBLEBUF);
        SDL_WM_SetCaption("Visualisation spectrale du Metal", NULL);
    
        do
        {
            fini = 0;
    
        /* Boucle principale */
    
        while (continuer && !fini)
        {
            SDL_PollEvent(&event); /* On doit utiliser PollEvent car il ne faut pas attendre d'évènement
                                    de l'utilisateur pour mettre à jour la fenêtre*/
            switch(event.type)
            {
                case SDL_QUIT:
                    continuer = 0;
                    break;
    
                case SDL_KEYDOWN:
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                    {
                    fini = 1;
                    FSOUND_Stream_Stop(musique);
                    }
                    break;
            }
    
            /* On efface l'écran à chaque fois avant de dessiner le graphe (fond noir */
            SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
    
    
            /* Gestion du temps
               -----------------
            On compare le temps actuel par rapport au temps précédent (dernier passage dans la boucle)
            Si ça fait moins de 25 ms (DELAI_RAFRAICHISSEMENT), alors on attend le
            temps qu'il faut pour qu'au moins 25 ms se soit écoulées. On met ensuite à
            jour tempsPrecedent avec le nouveau temps */
    
            tempsActuel = SDL_GetTicks();
            if (tempsActuel - tempsPrecedent < DELAI_RAFRAICHISSEMENT)
            {
                SDL_Delay(DELAI_RAFRAICHISSEMENT - (tempsActuel - tempsPrecedent));
            }
            tempsPrecedent = SDL_GetTicks();
    
    
    
            /* Dessin du spectre sonore
               ------------------------
    
            C'est la partie la plus intéressante. Il faut réfléchir un peu à la façon
            de dessiner pour y arriver, mais c'est tout à fait faisable (la preuve  )
    
            On récupère le pointeur vers le tableau de 512 floats via FSOUND_DSP_GetSpectrum()
            On travaille ensuite pixel par pixel sur la surface ecran pour dessiner les barres.
            On fait une première boucle pour parcourir la fenêtre en largeur.
            La seconde boucle parcourt la fenêtre en hauteur pour dessiner chaque barre.
            */
    
            spectre = FSOUND_DSP_GetSpectrum(); /* On récupère le pointeur vers le tableau de 512 floats */
    
            SDL_LockSurface(ecran); /* On bloque la surface ecran car on va directement modifier ses pixels */
    
            /* BOUCLE 1 : on parcourt la fenêtre en largeur (pour chaque barre verticale) */
            for (i = 0 ; i < LARGEUR_FENETRE ; i++)
            {
                /* On calcule la hauteur de la barre verticale qu'on va dessiner.
                spectre[i] nous renvoie un nombre entre 0 et 1 qu'on multiplie par 4 pour zoomer
                afin de voir un peu mieux (comme je vous avais dit). On multiplie ensuite
                par HAUTEUR_FENETRE pour que la barre soit agrandie par rapport à la taille
                de la fenêtre */
                hauteurBarre = spectre[i] * 4 * HAUTEUR_FENETRE;
    
                /* On vérifie que la barre ne dépasse pas la hauteur de la fenêtre
                Si tel est le cas on coupe la barre au niveau de la hauteur de la fenêtre */
                if (hauteurBarre > HAUTEUR_FENETRE)
                    hauteurBarre = HAUTEUR_FENETRE;
    
                /* BOUCLE 2 : on parcourt en hauteur la barre verticale pour la dessiner */
                for (j = HAUTEUR_FENETRE - hauteurBarre ; j < HAUTEUR_FENETRE ; j++)
                {
                    /* On dessine chaque pixel de la barre à la bonne couleur.
                    On fait simplement varier le rouge et le vert, chacun dans un sens différent
    
                    j ne varie pas entre 0 et 255 mais entre 0 et HAUTEUR_FENETRE. Si on veut l'adapter
                    proportionnellement à la hauteur de la fenêtre, il suffit de faire le calcul
                    j / RATIO, où RATIO vaut (HAUTEUR_FENETRE / 255.0)
                    J'ai dû réfléchir 2-3 minutes pour trouver le bon calcul à faire, mais c'est
                    du niveau de tout le monde. Il suffit de réfléchir un tout petit peu  */
                    setPixel(ecran, i, j, SDL_MapRGB(ecran->format, 255 - (j / RATIO), j / RATIO, 0));
                }
            }
    
            SDL_UnlockSurface(ecran); /* On a fini de travailler sur l'écran, on débloque la surface */
    
            SDL_Flip(ecran);
        }
        }while (continuer);
    
    
    
        /* Le programme se termine.
        On désactive le module DSP, on libère la musique de la mémoire
        et on ferme FMOD et SDL */
        FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), 0);
        FSOUND_Stream_Close(musique);
        FSOUND_Close();
    
        TTF_Quit();
        SDL_Quit();
    
        return EXIT_SUCCESS;
    }
    
    
    /* La fonction setPixel permet de dessiner pixel par pixel dans une surface */
    void setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
    {
        int bpp = surface->format->BytesPerPixel;
    
        Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    
        switch(bpp) {
        case 1:
            *p = pixel;
            break;
    
        case 2:
            *(Uint16 *)p = pixel;
            break;
    
        case 3:
            if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                p[0] = (pixel >> 16) & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = pixel & 0xff;
            } else {
                p[0] = pixel & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = (pixel >> 16) & 0xff;
            }
            break;
    
        case 4:
            *(Uint32 *)p = pixel;
            break;
        }
    }
    
    • Partager sur Facebook
    • Partager sur Twitter
      1 juin 2008 à 21:44:42

      un compilatuer C++ compile tres bien un code C sauf (tres) rares exceptios ;)
      • Partager sur Facebook
      • Partager sur Twitter
        2 juin 2008 à 9:04:55

        "mon compilateur me dit que la declaration etc...."
        Pourrais tu nous mettre l'erreur du compilateur telle quel?
        Parce que j'avoue que je comprend pas tout a fait merci.
        • Partager sur Facebook
        • Partager sur Twitter
          2 juin 2008 à 13:14:44

          En fait, je viens d'ajouter "Visualisation.h" dans Visualisation.c et il semblerait qu'il ne manque plus que les #include à régler, mon compilateur ne trouve plus les headers :o

          Mais, ça ne devrait pas me poser problème longtemps.


          EDIT: Oh, mais il y a un problème, le projet est un projet console(pour faire marcher Qt), et visualisation.c devrait être en SDL.

          Est-ce que quelqu'un sait comment faire, s'il vous plaît?
          • Partager sur Facebook
          • Partager sur Twitter

          Peut-on "mélanger" C et C++ ?

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown