IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Multithreading Discussion :

Conception de threads


Sujet :

Multithreading

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut Conception de threads
    Bonjour,

    Je suis entrain de faire un lecteur/éditeur audio pour mon projet de fin d'année. Pour jouer les sons j'utilise les librairies OpenAL et libsndfile. Mon petit problème est que quand je clic sur Lecture, toute mon interface graphique est bloqué et je suis obligé d'attendre la fin de la musique (normal). Donc l'utilisateur ne peut pas changer le volume, faire pause ou encore changer la balance.

    J'avais pensé à utiliser le module Phonon qui gère les threads, mais il ne permet pas de changer la balance (et si j'ai le temps, j'aimerais travailler sur le son 5.1, impossible avec Phonon)

    Pour faire tout ça j'ai une classe avec la partie graphique avec les signaux pour lancer la lecture, change le volume, etc... et une autre (PlayerAL) où je m'occupe des buffers, sources, lecture, etc...

    Je n'ai pas une grande expérience des threads (juste un peu en Java et s'est passé difficilement ) et je ne sais pas trop comment attaquer le morceau. J'ai lu pas mal de doc mais je suis encore dans le flou.

    Est ce qu'il est possible de mettre les signaux dans un thread ?
    Est ce que je dois faire hériter ma classe PlayerAL de QThread ?

    Merci d'avance
    Olivier

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Salut.
    as tu regardé un peu la FAQ?

    es ce que PlayerAL est un QObject?

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    Yop,

    Désolé pour le temps de réponse.
    Je fais hérité mon objet PlayerAL à QObject.

    Oui j'ai la FAQ sur les threads. J'avais penseé à mettre ceci en place : http://qt.developpez.com/faq/?page=T...ad-signal-slot

    Mais je ne suis pas sûr que ce soit ce qu'il faut. Dans mon cas le Thread 1 serait mon interface graphique, le thread interne au 2ème serait mon objet PlayerAL et dans le 2ème Thread j'implémente la méthode run() avec le PlayerAL et les signaux.

    En faite en l'écrivant je comprend mieux. En faites on crée un intermédiaire entre les deux classes.

    Je vais tester ça cet après-midi

    Merci
    Olivier

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    Après pas mal d'essais, ce que j'ai codé ne semble pas bon. Je ne peux toujours pas accéder à mon interface graphique pendant que je joue un son et maintenant le son est hachuré et quand je lance la lecture, la totalité de mon CPU est utilisé.
    Pour l'utilisation du CPU j'ai regardé ici. Or je ne peux pas mettre de sleep dans ma boucle de lecture puisque je ne suis pas dans la classe du thread et comme mssleep() est protected...
    Pour les autres problèmes j'ai pas trouvé de solutions.

    Je vous montre mon code.

    PlayerThread.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #ifndef PLAYERTHREAD_H
    #define PLAYERTHREAD_H
     
    #include <QThread>
    #include <al.h>
    #include <alc.h>
    #include "PlayerAL.h"
     
    class PlayerThread : public QThread{
        Q_OBJECT
     
    private :
        PlayerAL player;
    protected:
        void run();
    public:
        void loadBuffer(const std::string &);
        void changeVolume(ALfloat);
        void changeBalance(int);
        void setCurrentBuffer(int);
        bool isPlaying();
    signals:
        void previousBuffer();
        void play();
        void pause();
        void stop();
        void nextBuffer();
    };
    #endif // PLAYERTHREAD_H
    PlayerThread.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include "PlayerThread.h"
    using namespace std;
     
    void PlayerThread::run(){
        connect(this,SIGNAL(previousBuffer()),&player,SLOT(previousBuffer()));
        connect(this,SIGNAL(play()),&player,SLOT(play()));
        connect(this,SIGNAL(pause()),&player,SLOT(pause()));
        connect(this,SIGNAL(stop()),&player,SLOT(stop()));
        connect(this,SIGNAL(nextBuffer()),&player,SLOT(nextBuffer()));
        exec();
    }
     
    void PlayerThread::loadBuffer(const string & path){
        player.loadBuffer(path);
    }
     
    void PlayerThread::changeVolume(ALfloat value){
        player.changeVolume(value);
    }
     
    void PlayerThread::changeBalance(int value){
        player.changeBalance(value);
    }
     
    void PlayerThread::setCurrentBuffer(int index){
        player.setCurrentBuffer(index);
    }
     
    bool PlayerThread::isPlaying(){
        return player.isPlaying();
    }
    Player.cpp (partie de la lecture)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void PlayerAL::play(){
        if(!buffers.empty()){
            alSourcei(source,AL_BUFFER,buffers[currentBuffer]);
            alSourcePlay(source);
            ALint status;
            playing=true;
            do{
                ALfloat seconds;
                alGetSourcef(source,AL_SEC_OFFSET, &seconds);
                cout<<"reading..."<<std::fixed<<seconds;
                alGetSourcei(source, AL_SOURCE_STATE, &status);
            }while(status==AL_PLAYING);
            alSourceUnqueueBuffers(source,1,&buffers[currentBuffer]);
            playing=false;
        }
    }
    Merci d'avance
    Olivier

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    SAlut.
    A quoi correspond PlayerThread ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    do{
                ALfloat seconds;
                alGetSourcef(source,AL_SEC_OFFSET, &seconds);
                cout<<"reading..."<<std::fixed<<seconds;
                alGetSourcei(source, AL_SOURCE_STATE, &status);
            }while(status==AL_PLAYING);
    si tu fais cela, tu bloque l'eventloop. Tu devrais regarder le thread à côté du tien. J'y explique beaucoup de choses.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    Si je reprends l'exemple d'ici, ThreadEmetteur est l'interface graphique, interThreadReceveur est PlayerAL et threadReceveur est PlayerThread.

    Pour la lecture du son, je suis obligé de faire cette boucle pour lire le buffer.
    Je vois pas trop ce que c'est un event loop. J'ai lu que c'est ce qui était lancé par la commande .exec() mais je vois pas ce que ça représente.

    J'ai lu et relu la FAQ et je vois pas ce que je rate.

    Olivier

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par olivier.a Voir le message
    Pour la lecture du son, je suis obligé de faire cette boucle pour lire le buffer.
    tu ne fait que regarder l'état d'openAl.

    Je vois pas trop ce que c'est un event loop.
    C'est une boucle
    http://qt.developpez.com/doc/latest/qeventloop/
    Plutôt que de faire ta boucle, tu peux utiliser un timer et regarder ou en est la lecture. Ceci de permettra de faire des play et des stop pendant.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    yop,

    J'ai retiré la boucle et en faites, oui, elle ne sert pas à lire le buffer... J'étais persuadé de ça depuis le début et j'ai jamais regardé de plus près.
    Du coup, j'ai retiré la boucle puisque j'en ai pas besoin. J'ai une méthode pause() et stop() qui s'occupe de tout si l'utilisateur veut arrêter la lecture. Et donc maintenant je peux accéder à l'interface graphique pendant la lecture.

    J'ai remarqué que le son était moins haché qu'avant. J'imagine que c'est parce qu'il y a moins de calcul à faire.
    Par contre contrairement à avant mon CPU n'est plus utilisé à 100% mais dans les 10-15% et une fois sur deux mon son de 10sec est lu en même pas une.

    Donc il me reste plusque cette histoire de hachage de son.
    Je vais chercher ça sur google

    Merci pour ton aide Yan.

    Olivier

  9. #9
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Par contre contrairement à avant mon CPU n'est plus utilisé à 100% mais dans les 10-15% et une fois sur deux mon son de 10sec est lu en même pas une.
    ca c'était ton while

    Citation Envoyé par olivier.a Voir le message
    J'ai remarqué que le son était moins haché qu'avant. J'imagine que c'est parce qu'il y a moins de calcul à faire.
    C'est surement parceque OpenAl n'as plus de buffer à lire et stop. Puis tu le redémarre. Normalement, il faut l'alimenter régulièrement pendant la lecture. Il y as une méthode qui permet de connaitre le nombre de buffer déjà lue.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    yop,

    j'ai vu mon chargé de projet cet après-midi et apparemment il bloque aussi (héhé).

    En faisant ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    alSourcei(source,AL_BUFFER,buffers[currentBuffer]);
    je dis à ma source quel buffer elle va devoir lire.

    Et avec cette commande :
    je pensais qu'on envoyait toutes les données concernant la musique à la carte son. Mais dans ce cas ça ne devrait pas hachuré. Mais en même temps si on envoie pas tout d'un coup, je vois pas comment la boucle que je faisais pour avoir le temps fonctionnait, parce qu'on fait bien les choses instruction par instruction et si on envoie en continue, quand la méthode play est fini, on fini la lecture du son. Et donc la boucle devrait afficher juste la durée du son.
    Il me semble avoir vu un schéma qui représente tout ça mais j'arrive pas à remettre la main dessus.
    J'ai changé la priorité du thread pour voir et il n'y pas de changement.

    Et après la lecture, je retire le buffer de la source pour éviter de me retrouver avec une playlist.

    Je suis dans le flou là.

  11. #11
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    http://www.devmaster.net/articles/op...ls/lesson8.php
    sinon regarde sfml. Je m'étais basé sur ce code pour faire du streaming audio.

    Vue que c'est des quelstion OpenAl, je te conseil de poser ta question sur ce forum :
    http://www.developpez.net/forums/f14.../audio/openal/

  12. #12
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2011
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2011
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    Vu que le problème est arrivé une fois le thread mis en place, je pensais que ça venait de là.

    Je vais lire ton lien (il y a pas mal de lecture )

    J'espère que je vais pas avoir besoin de changer de librairie, ça me ferait ch*er de recoder plus ou moins tout.

  13. #13
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par olivier.a Voir le message
    J'espère que je vais pas avoir besoin de changer de librairie, ça me ferait ch*er de recoder plus ou moins tout.
    OPenAl marche trés bien et c'est plutôt une valeur sure.

    Dans le lien que je t'ai donnée, regarde bien la fonction ogg_stream::update()

Discussions similaires

  1. Question de conception: thread
    Par Flophx dans le forum POSIX
    Réponses: 27
    Dernier message: 22/02/2007, 00h02
  2. [Conception] Thread local
    Par smutmutant2003 dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 29/01/2007, 21h04
  3. [Conception] Threading
    Par mouloude dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 08/12/2004, 10h17
  4. Réponses: 7
    Dernier message: 19/10/2004, 19h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo