faire varier le volume sonore sur un microcontroleur
Répondre à la discussion
Affichage des résultats 1 à 11 sur 11

faire varier le volume sonore sur un microcontroleur



  1. #1
    invite9426e977

    faire varier le volume sonore sur un microcontroleur


    ------

    hello tout le monde.

    je voudrais faire varier numériquement le volume d'un flux sonore 16bits 44.1Khz stereo qui transite via un microcontroleur 16 bits mais je rencontre quelque obstacles.

    je pensais faire des divisions : /2 /3 /4 etc...
    mais ça ne fonctionne pas proprement, la variation n'est pas linéaire et la première étape est trop importante.

    donc j'ai fait ceci :

    res = flux / volume * 4;

    en sachant que volume est au mini = 4 et plus ça augmente, plus le son diminue.

    mais je rencontre un problème de diminution de la qualité audio (perte d'infos...) et d'augmentation du souffle.

    j'ai essayé de passer en float ou en double (pour pouvoir faire le *4 avant la div...) mais c'est trop lent avec ce format et ça merde.

    avez vous des solutions a me proposer ?
    dans l'idéal, en travaillant avec des formats rapides a traiter.
    je ne peux pas modifier le volume directement DANS le codec car je dois faire un mixage a l'interrieur du micro.

    merci d'avance,
    marc.

    -----

  2. #2
    Murayama

    Re : faire varier le volume sonore sur un microcontroleur

    Bonjour!

    Dans un microcontrôleur, il faut à tout prix éviter:
    - Les float;
    - Les divisions;
    Ou du moins ne les utiliser quand on ne peut vraiment pas faire autrement.

    En admettant que vous ne puissiez vous passer de float:
    Au lieu de diviser par 2, avez-vous pensé à multiplier par 0,5?
    Exemple: vous récupérez un gain compris entre 0 et 1, et vous multipliez l'entrée par ce gain?

    On notera qu'il est possible de faire la même choses sans float, tout en gardant la même résolution.

    Pascal

  3. #3
    invitea3c675f3

    Re : faire varier le volume sonore sur un microcontroleur

    Question niaiseuse: connais-tu les potentiomètres électroniques ?

  4. #4
    invite29971eb1

    Re : faire varier le volume sonore sur un microcontroleur

    Citation Envoyé par Murayama Voir le message
    Bonjour!

    Dans un microcontrôleur, il faut à tout prix éviter:
    - Les float;
    - Les divisions;
    Ou du moins ne les utiliser quand on ne peut vraiment pas faire autrement.

    En admettant que vous ne puissiez vous passer de float:
    Au lieu de diviser par 2, avez-vous pensé à multiplier par 0,5?
    Exemple: vous récupérez un gain compris entre 0 et 1, et vous multipliez l'entrée par ce gain?

    On notera qu'il est possible de faire la même choses sans float, tout en gardant la même résolution.

    Pascal
    Un compilo pas trop idiot fera un décalage à droite en lieu et place d'une division par un entier mais effectivement si on peut éviter les float, c'est d'autant mieux, à part sur les micros équipés d'une FPU.

    Si je devais faire la même chose, je commencerai par multiplier l'échantillon par un volume entier, entre 0 et 255 avant de décaler le signal de 8 bits à droite (division par 256). Ainsi, on arrive à un volume réglable entre 0 et 255/256. Bien sur, il faut faire attention aux casts et s'assurer que la multiplication soit sur une donnée 32 bits. Si le cast fonctionne mal (et c'est l'essence même du C que de foutre le bordel dans les types des variables), le résultat sera casté en 8 ou 16 bits d'ou la dégradation probable du son.....

  5. A voir en vidéo sur Futura
  6. #5
    invite9426e977

    Re : faire varier le volume sonore sur un microcontroleur

    je dois faire un mixage, j'ai plusieurs entrées, plusieurs sorties, chacune a des niveaux différents qui vont varier, donc je ne peux pas utiliser de potard numérique.

    Murayama, j'ai déja essayé de faire un multiplication mais je dois donc avoir un niveau trés bas, donc peu d'octets et donc basse qualité...
    d'autres idées ?

  7. #6
    invite936c567e

    Re : faire varier le volume sonore sur un microcontroleur

    Bonjour

    Le réglage de volume est un simple problème de multiplication à virgule fixe. On le résout un peu différemment selon les capacités de l'unité arithmétique du micro-contrôleur, selon qu'on dispose d'une division câblée, d'une multiplication câblée, ou juste d'un décalage et d'une addition.

    L'opération arithmétique doit, quoi qu'il en soit, être menée avec une précision supérieure que les données d'entrée et de sortie, et dans un ordre qui ne fasse pas perdre de bits significatif.

    Ainsi, pour des données sur 16 bits, on effectue le traitement sur 32 bits (parfois moins si cela permet une optimisation), et le résultat est tronqué sur 16 bits à la fin de l'opération.

    Voici un exemple de traitement :

    Code:
    // signal d'entrée : –32768 ≤ flux ≤ 32767
    // réglage de volume : 0 ≤ volume ≤ 65535
    // signal de sortie = flux*(volume/65536)
    
    int16_t reglage_volume( int16_t flux, uint16_t volume )
    {
      int32_t res = flux;   // extension à 32 bits du mot d'entrée
                            //  –32768 ≤ res ≤ 32767
    
      res *= volume;        // multiplication par le coefficient de volume
                            //  –2147450880 ≤ res ≤ 2147385345 
    
      res >>= 16;           // conservation des 16 bits de poids fort
                            // –32768 ≤ res ≤ 32766
    
      return (int16_t)res;
    }
    Cet exemple peut être grandement amélioré (par exemple pour optimiser le temps d'exécution, ou pour présenter une atténuation unitaire ou une atténuation avec une progression logarithmique) ou adapté pour s'intégrer à d'autres traitements (mixage, filtrage).

  8. #7
    paulfjujo

    Re : faire varier le volume sonore sur un microcontroleur

    Bonjour,

    Citation Envoyé par nordiste Voir le message
    d'autres idées ?
    un ampli OP programmable genre MSP6S22
    Gain ajustable de 1,2,4,5,8,10,16,32

  9. #8
    Murayama

    Re : faire varier le volume sonore sur un microcontroleur

    Bonjour!

    Un compilo pas trop idiot fera un décalage à droite en lieu et place d'une division par un
    entier mais effectivement si on peut éviter les float, c'est d'autant mieux, à part sur les
    micros équipés d'une FPU.
    Deux problèmes:
    - Ce que vous dites n'est vrai QUE pour les puissances de 2. Vous ne pouvez pas diviser
    par 3 en décalant.
    - Ce que vous dites n'est vrai QUE si le diviseur est connu à la compilation, ce qui n'est
    pas le cas pour un gain. Essayez de compiler:
    Code:
    int a = 10;
    int b = a/2;
    Effectivement, le compilateur fait un décalage à droite.
    Code:
    int div(int a, int b) {
        int c = a / b;
        return c;
    }
    Là, vous verrez que c'est bien une division, pas un shift puisque le compilateur
    n'a aucun moyen de savoir si et quand le diviseur sera une puissance de 2.

    De plus, je me plaçais dans le cas où l'on ne peut pas se passer de float:
    1 = 0x3F800000
    0.5 = 0x3F000000
    On n'y arrive donc pas non plus par décalage.

    Si le cast fonctionne mal (et c'est l'essence même du C que de foutre le bordel dans les
    types des variables), le résultat sera casté en 8 ou 16 bits d'ou la dégradation probable
    du son.....
    Je vois ce que vous voulez dire, mais ce n'est pas imputable au C. Ça tient surtout
    au programmeur qui manque de précautions ou connaît mal son hardware. Et il y a aussi
    le fait que tous les compilateurs embarqués donnent parfois des résultats surprenants.
    C'est pour cela que l'on passe en général beaucoup plus de temps en test qu'en codage.

    Exemple: compilateur IAR, MSP430.
    Code:
    uint16 a = 20000;
    uint16 b = 40000;
    uint32 c = a * b;
    On pourrait s'attendre à trouver 800000000, mais si on fait l'expérience, on trouve 2048
    La raison est probablement que le compilateur évalue d'abord a * b avant de l'assigner
    à C, d'où saturation. Je me suis fait avoir un paquet de fois. La solution est de faire:
    Code:
    uint32 c = a;
    c *= b;
    C'est d'ailleurs pour cette raison que PA5CAL a écrit sa fonction de cette façon: int32 res = flux.
    (assignation immédiate dans un int32).
    Le problème en programmation embarquée, c'est qu'il faut être au courant de ce qui se
    fait à l'intérieur. D'aucuns préconisent de connaître l'assembleur, mais je pense que
    c'est la connaissance de la structure interne qui importe. Il n'y a aucune fonction
    faisable en assembleur et pas en C. Et puis il vaut mieux aussi utiliser le hard au maximum.
    Exemple (toujours MSP430): la multiplication ci-dessus prend 500 cycles d'horloge si
    on n'utilise pas le multiplieur hardware. Si on l'utilise, par contre, on fait la même
    chose en 8 cycles TTC. Et il n'y a pas besoin de décaler le résultat.

    Code:
    int16 input;
    int16 gain;
    int16 output;
    [...]
    MPY32CTL0 |= MPYFRAC;	//	Set fractional mode
    MPYS = input;			//	Set input
    OP2 = gain;				//	Set second operand (multiplication is performed here)
    output = RESHI;			//	Get result
    MPY32CTL0 &= ~MPYFRAC;	//	Unset fractional mode.
    Pascal

  10. #9
    invite9426e977

    Re : faire varier le volume sonore sur un microcontroleur

    Merci Merci Merci PA5CAL
    avec ta technique ça marche bien
    et pas de perte de qualité

  11. #10
    invite29971eb1

    Re : faire varier le volume sonore sur un microcontroleur

    Citation Envoyé par Murayama Voir le message
    Je vois ce que vous voulez dire, mais ce n'est pas imputable au C. Ça tient surtout
    au programmeur qui manque de précautions ou connaît mal son hardware. Et il y a aussi
    le fait que tous les compilateurs embarqués donnent parfois des résultats surprenants.
    C'est pour cela que l'on passe en général beaucoup plus de temps en test qu'en codage.

    Exemple: compilateur IAR, MSP430.
    Code:
    uint16 a = 20000;
    uint16 b = 40000;
    uint32 c = a * b;
    On pourrait s'attendre à trouver 800000000, mais si on fait l'expérience, on trouve 2048
    La raison est probablement que le compilateur évalue d'abord a * b avant de l'assigner
    à C, d'où saturation. Je me suis fait avoir un paquet de fois. La solution est de faire:
    Code:
    uint32 c = a;
    c *= b;
    Mais ce problème n'est pas lié au micro mais au C lui-même qui considère que le résultat d'une opération entre int doit forcément être un int, même si on lui a déclaré le contraire. C'est le fameux cast automatique, inexistant dans des langages tels que le Pascal.

  12. #11
    Murayama

    Re : faire varier le volume sonore sur un microcontroleur

    Bonjour!

    Mais ce problème n'est pas lié au micro mais au C lui-même qui considère
    Je n'ai pas dit que c'était lié au micro, mais à l'utilisateur. Et je ne pense pas que ce soit
    un "problème" du C, mais une caractéristique, seulement.
    Ça devient plus philosophique ou religieux qu'autre chose, mais de mon point de vue,
    c'est surtout un problème d'utilisateur. C'est comme une scie à ruban et une tronçonneuse,
    les deux coupent, mais pas de la même façon, et suivant l'habitude, on préfère l'une ou
    l'autre.
    Quand on "vient" du Pascal (ce qui est aussi mon cas), on trouve tout un tas de choses
    illogiques au début, et ça produit des discussions interminables sur les forums, avec
    insultes à l'appui pour décréter que l'un ou l'autre langage est nul, etc... C vs Pascal,
    PHP vs Perl, etc... Il y a même des "guerres" entre les intégristes du C et les
    afficionados du C++, C'est dire! Il y en a même qui s'engueulent en considérant qu'il
    est plus logique de mettre l'accolade en fin de ligne ou au début de la suivante, etc...

    Il y a des évangélistes du Pascal : http://www.pascal-central.com/ppl/chapter4.html,
    et comme n'importe quel évangéliste, tout ce qui est dit est discutable. D'ailleurs
    quand on me sort "nothing can be further from truth", quel que soit le domaine, j'ai
    tendance à me méfier. Il y a certainement la même faune d'individus en faveur du C.

    Le C lui-même n'est pas un problème. Il fonctionne d'une certaine façon, le Pascal
    fonctionne d'une autre façon, il faut faire avec l'un ou l'autre suivant ses préférences,
    habitudes ou demandes du client. Toutes les autres considérations ne sont que des
    histoires de goût personnel.

    Pascal

Discussions similaires

  1. Faire varier la luminosité d'une led 1w
    Par inviteb037bc5c dans le forum Électronique
    Réponses: 18
    Dernier message: 15/01/2013, 12h36
  2. Faire varier un voltage
    Par invite477a86e0 dans le forum Électronique
    Réponses: 16
    Dernier message: 23/09/2011, 15h17
  3. faire varier la frequence
    Par invitedb8fb805 dans le forum Électronique
    Réponses: 10
    Dernier message: 05/01/2009, 11h52
  4. Faire varier une résistance
    Par invite96a93ba8 dans le forum Électronique
    Réponses: 8
    Dernier message: 07/12/2005, 23h33
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...