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

Algorithmes et structures de données Discussion :

[Signal] [Audio] Un vibrato magique


Sujet :

Algorithmes et structures de données

  1. #1
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut [Signal] [Audio] Un vibrato magique
    Salut !

    Comment calculer un signal dont la fréquence varie dans le temps ?
    On a :
    - une fréquence de départ
    - une fréquence d'arrivée
    - une durée pendant laquelle la fréquence de départ tend (croît ou décroît selon que...) vers la fréquence d'arrivée
    - au delà de la durée, la fréquence est verrouillée sur la fréquence d'arrivée.

    Pour être plus précis, il s'agit de faire un petit automate me permettant de calculer ce signal échantillon par échantillon.
    C'est ni plus ni moins qu'un signal de commande pour obtenir un vibrato d'un type particulier, en utilisant l'automate en tant que LFO.

    J'ai essayé plusieurs méthodes mais elles n'apportent pas le résultat souhaité.

    Voici la première, sans doute la plus "primaire"... parce que aussi simple que ça, ça aurait été trop beau !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int Time; //durée en terme d'échantillons pour la variation de fréquence
    int Compteur = 0;
    int Sample = 0;
    double Freq_dep;
    double Freq_arr;
    double fo;
    double result;
    #define Pi 6.28318530717958
    Précalculé pour soulager le temps de calcul échantillon par échantillon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double step = (Freq_arr - Freq_dep) / Time; //au premier abord...
    L'automate calcule les échantillons ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if(Compteur <= Time)
        {
        fo = Freq_dep + (step * Compteur); //au premier abord... 
        Compteur++;
        }
    d = fmod(Sample * fo * Pi / 44100.0, Pi); //rem Pi vaut 2*pi
    result = sin(d);
    Sample++;
    Le résultat est catastrophique dans la mesure où la variation obtenue est trop grande ce qui se traduit par un changement brutal de fréquence au moment où l'algo se verrouille sur la fréquence d'arrivée.

    Sinon pour les autres essais... je les garde en tant que "Automates Gazouilleurs" !

    A plus !

  2. #2
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    il suffit de calculer la phase dans le temps!
    Phi(t+dt) = phi(t) + dt * freq(t)*2*Pi
    on peut choisir Phi(0) = 0



    Signal(t) = sin (Phi(t))

    pour vous
    f(t0) = F0 à t=t0
    entre t0 et t1
    f(t) = F0 + (F1-F0) * (t-to)/(t1-t0)
    si t > t1
    f(t) = F1;

    Evidement ne pas oublier Nyquist! : dt doit être < T/2

    J'avais déjà répondu à un sujet similaire il y a quelques temps. Voir
    http://www.developpez.net/forums/showthread.php?t=70455

  3. #3
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    f(t) = F0 + (F1-F0) * (t-to)/(t1-t0)
    Si le terme to est une erreur de frappe au lieu du terme t0 ... alors je fais la même chose ... il me semble en tout cas !

    A plus !

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    alors je fais la même chose
    Evidement to=t0!
    donc on est d'accord sur F(t)

    Depuis ici, on ne fait plus la même chose!!

    pour construire le signal s(t) on le digitalise pour t = n* dt. On note alors les échantillons Sn
    on démarre avec P0 = 0 (ou une phase de votre choix )
    S0 = sin ( P0 )

    Par récurrence on calcule
    1- P(n+1) = P(n) + dt * F( dt*(n+1) ) *2*Pi
    2- S(n+1) = sin(P(n+1))


    Il n'y aura pas de changement brutal de f ni de discontinuité.
    Ne pas oublier de choisir dt suffisamment petit, en tout cas < min(T1/2, T2/2) où T1 et T2 sont les 2 périodes départ & fin

    Votre algorithme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if(Compteur <= Time)
        {
        fo = Freq_dep + (step * Compteur); //au premier abord... 
        Compteur++;
        }
    d = fmod(Sample * fo * Pi / 44100.0, Pi); //rem Pi vaut 2*pi
    result = sin(d);
    Sample++;
    est faux car on recalcule la phase pour l'instant t en considérant tout le signal à la fréquence f(t) depuis t=0 => elle avance trop vite ( si F2 > F1 )
    ce qui donne un signal calculé qui monte trop haut en fréquence.
    Il faut uniquement estimer les incréments sur la phase comme proposé
    plus haut
    Si on compare votre algorithme avec ma proposition, on obtient les résultats annexés.
    J'ai simulé sous mathcad f_start= 10Hz, f_end=50Hz avec 10'000 points de calculs. Le sacn est fait en 5 secondes ( dt = 5/10'0000 )
    On note que vous finissez avec une valeur moyenne de 90 Hz alors que l'on souhaitait scanner de 10 à 50 Hz.
    L'algorithme travaillant du l'évolution de la phase fini avec un f moyen de 50 Hz ce qui était prévu par le problème.
    Evidemment, votre erreur devient de plus en plus sensible avec le temps, puisque la durée sur laquelle on intègre une mauvaise valeur de dPhi s'accroît.
    Images attachées Images attachées  

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    C'est fait ! Un grand merci !

    J'ai eu un problème de raccordement de phase à la fin de la progression en fréquence, donc lorsque l'oscillateur commençait à se verrouiller sur F2.
    J'ai donc fait (ce qui m'a paru logique) :

    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
    if(TimeCounter <= Time)
        {
        //diff est précalculé : (EndFreq - StartFreq) / ProgressTime
        f1 = StartFreq + (diff * TimeCounter);
        w1 = f1 * 2.0 * pi;
        //dt est précalculé : 1/44100
        fo = fo + (dt * w1); //On a sans doute un cumul d'erreurs, cause du prob de raccordement final
        phi = fo; //je mémorise l'angle
        TimeCounter++;
        }
    else
        {
        //phi est donc le dernier angle donné par la progression
        //w2 est précalculé : EndFreq * 2 * pi
        fo = phi + Sample * w2 * dt; //je déphase de phi pour le raccordement 
        Sample++;
        }
    result = sin(fo);
    J'ai vérifié le résultat en TBF et en BF, y compris en tant que vibrato et ça semble fonctionner correctement !

    Celà dit... mon algo est-il absolument parfait ?

    Encore et encore, un grand merci !

    A plus !

  6. #6
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    pour raccorder rien de plus simple.
    Avec mes notations du post précédant,
    on arrive à F2 pour
    Tx = np * dt
    avec une phase
    Px = P(np)
    On va donc continuer avec un sin de fréquence F2 dont la phase vaut Px à Tx
    on peut continuer l'algorithme précedent en ne changeant plus F
    =>
    Par récurrence on calcule n > np
    1- P(n+1) =
    P(n) + dt * F2 *2*Pi = Px + (n-np) * dt * F2 *2*Pi =
    Px + F2 *2*Pi * ( t-Tx)
    2- S(n+1) = sin(P(n+1))

    cela revient alors à calculer la fonction
    sin ( 2Pi * F2 * ( t-Tx ) + Px )
    < fréquence F2, Phase Px pour t = Tx >

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    J'ai fait une petite erreur dans la recopie du code que j'ai montré.
    En effet, le compteur Sample est incrémenté dans le else puisqu'il ne concerne que l'échantillonnage de la fréquence finale et non celle de la variation.
    Hors du else, on déphaserait encore plus !

    donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    else
        {
        fo = phi + (Sample...
        Sample++;
        }
    J'ai apporté la correction dans la réponse.

    Sinon, j'ai décliné avec d'autres formes d'ondes et ça semble toujours bien fonctionner (... on ne sait jamais !!!) !

    Merci pour toutes ces précieuses informations !

    A plus !

  8. #8
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    Il faut faire attention à la phase.
    Si il est question d'un signal audio que l'on passera dans des HP,
    une erreur sur la phse conduit à une discontinuité du signal temporel.
    Cela peut implique qu'après l'ampli, il y ait un très forte variation de la tension ( juste limitée pa la bande passante de l'électronique ).
    ce la implique
    1- un tres fort signal acoustique type 'pulse'
    2- un risque certain d'endomager les enceintes acoustiques ( en + de ses oreilles ! )

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    dans un de vos posts, vous notez
    f(t) = F0 + (F1-F0) * (t-to)/(t1-t0)
    En fait il serait plus judicieux d'utiliser une échelle en dB sur f(t)

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    F = F1 + (F2 - F1) * sin( t/T * pi/2) pour t de 0 à T

    On obtient une variation intéressante, tout comme la première. (je n'ai fait qu'un seul test donc...)

    A plus !

  11. #11
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Par rapport à ce que j'ai donné, on peut aussi utiliser :

    sin(sin(...

    Et dans un même ordre d'idée (avec un résultat plus "gothique"):
    1-cos(1-cos(...

    Il y a aussi une variation s'appuyant sur la formule qui permet de calculer la charge d’un condensateur

    Uc(t) = E.(1- e-t/RC)

    Pour ramener les 63% à 100% lorsque t/T = 1, donc lorsque F doit être égal à F2 je fais :

    1- e-t/T / 1- e-1

    Sans doute existe-t-il une fonction permettant à l’aide d’un terme (ou plusieurs) de faire glisser l’allure de la variation d’une convexité à une concavité (c’est l’idée que je me fais ici de la représentation graphique de cette fluctuation de l’allure, un peu comme celle des courbes de Bézier) en passant par une variation (centrale) linéaire ?
    Mais bon…à partir de là… je disjoncte !

    Celà dit... ça me fait 6 types de variations... et il n'est pas certain que de légères fluctuations soient d'un grand intérêt !

    A plus !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 29/03/2007, 14h43
  2. Amplifier un signal audio
    Par flammeon dans le forum C++
    Réponses: 13
    Dernier message: 25/09/2006, 16h27
  3. Récuperer le signal audio d'un fichier .wav
    Par vienin dans le forum Multimédia
    Réponses: 2
    Dernier message: 11/10/2005, 16h25
  4. [TMS320C6416] FFT et IFFT sur un signal audio...
    Par 0x4e84 dans le forum Autres architectures
    Réponses: 1
    Dernier message: 18/04/2005, 20h21
  5. Réponses: 2
    Dernier message: 08/11/2004, 22h31

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