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

C++Builder Discussion :

2Scroll Bar, 2Zoomeurs et une image [Sources]


Sujet :

C++Builder

  1. #1
    Membre très actif

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Par défaut 2Scroll Bar, 2Zoomeurs et une image
    bonjour, il y a-t-il une manière simple (plus simple) que celle que j'ai réussi à utiliser pour entre autre afficher la courbe d'un wav dans un canvas et pouvoir zoomer et déplacer la courbe ?
    (ma solution est d'utiliser TImage, de charger un fichier bmp blanc de 500x500pixels, de dessiner sur le canvas du bitmap, de mettre la timage en transparent = true, et strech = true, de mettre des labels par exemple pour cacher les parties que l'on ne veut pas afficher (on obtient une image de 50x50pixels par exemple en positionnant les labels), puis de mettre des codes sur les onchange de deux scroll bar (change le Image->Left...), pareil pour le zoom: change le Image->Width ... c'est compliqué mais ça marche, et c'est assez rapide même avec une image de 5mo, par contre on obtient des effets de repaint, show légers mais assez dé plaisants

    après pour ce qui est de la synthèse de la courbe d'un fichier wav; je trouve les fonctions MoveTo et LineTo un peu trop lentes :- ) ... 5min pour un fichier de 10MO? je n'ai pas réussi à utiliser la méthode qui consiste d'abord faire un esemble de POINT points; points[0].x = ; points[1].y =; points[1].x = ; points[1].y =; points[i].x = ; points[i].y =; ...

    je suis en train de regarder les possibilités de TDrawGrid, mais si vous pouvez me donner des conseils pour arriver plus vite à un résultat correct... merci d'avance

  2. #2
    Membre très actif

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Par défaut
    je n'ai donc pas réussi à utiliser POINT, mais apparement TPoint fonctionne, par contre j'ai un petit probleme, voici le code pour dessiner une sinusoide dans une TPaintBox (à mettre dans l'évènement OnPaint de la paintbox par exemple), sans oublier #include <math.h> :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int nbr_x=1000; double temp_y; int gx;
    TPoint *points= new TPoint[nbr_x];
     
    for (gx=0; gx < nbr_x; gx++) {
      temp_y = 100 - sin(float(gx/20))*50;
      points[gx].x = gx;
      points[gx].y = temp_y;
      }
      ((TPaintBox *)Sender)->Canvas->Pen->Color = clTeal;
      ((TPaintBox *)Sender)->Canvas->Polyline(points,nbr_x-1);
    pourquoi obtient ce résultat bizarre (comme si le sinus était converti en entier...) ? pourtant temp_y est de type double ? bon si vous pouvez m'aider merci d'avance

    Balises [Code] rajoutées par Ricky81
    Pensez y à l'avenir

  3. #3
    Membre Expert

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 407
    Par défaut
    Salut !

    Ca fait deux questions alors je répondrais (enfin je vais essayer) uniquement à la première :

    Dans un premier temps bien t'assurer que tu dessines bien les samples, en tenant
    compte bien sûr des informations contenues dans le header. Voir sur WOTSIT (avec GOOGLE)
    au cas où le wav serait d'un format complexe.
    Par exemple, voici une class perso pour le header d'un wav du type WAVE_FORMAT_PCM :

    class TFilePCMWaveHeader
    {
    public :
    char RiffID[4]; // "RIFF"
    int Riffsize; // taille du fichier wav - 8
    char WaveID[4]; // "WAVE"
    char FmtID [4]; // "fmt "
    unsigned int Formatsize; // taille du bloc Format (ici 16)
    //Format bloc
    unsigned short FormatTag; // 1 = WAVE_FORMAT_PCM
    unsigned short Channels; // 1 = mono, 2 = stéréo
    unsigned int SamplesPerSec; // 22050 ou 44100 = fréquence
    unsigned int AvgBytesPerSec; //
    unsigned short BlockAlign; // Nombre d'octets par samples (1, 2 ou 4)
    unsigned short BitsPerSample; // 8 ou 16
    //Data bloc
    char DataID[4]; // "data"
    unsigned int DataSize; // taille en octets du bloc Samples qui suit
    //Samples[] // les samples commencent donc à + 44
    // ce sont soit des bytes soit des shorts
    // simples ou par couple (mono ou stéréo)
    };
    la propriété AvgBytesPerSec représente le nombre d'octets qui vont être joués pendant
    une seconde c'est à dire SamplesPerSec * BlockAlign

    Pour ce qui est du graphisme, l'idée du stretch est très originale, mais à mon avis peu
    fonctionnelle dès lors que l'on veut faire du scrolling.
    Il est toujours préférable de travailler avec un bitmap que l'on recopie ensuite sur un objet,
    le mieux étant directement sur la form, via le Canvas bien sûr !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Graphics::TBitmap *Scope = new Graphics::TBitmap;
    Et pour le dessiner, ça peut ressembler à ça:

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    void __fastcall TForm1::DrawScope()
    {
    if(Scope != NULL)
        {
        int w = ClientWidth;
        int h = ...;
        if(Scope->Width != w)
            {
            Scope->Width = w;
            }
        if(Scope->Height != h)
            {
            Scope->Height = h;
            }
        //Effacer le bitmap
        TCanvas *C = Scope->Canvas;
        C->Pen->Color = clBlack;
        C->Pen->Mode = pmCopy;
        C->Pen->Style = psSolid;
        C->Brush->Color = clBlack; 
        C->Brush->Style = bsSolid;
        C->Rectangle(0,0,w,h);
        //il faut savoir si on doit dessiner 1, 2 ou plusieurs canaux
        //Ce qui vaut pour un vaut pour d'autres, en dehors de la couleur de la trace
        C->Pen->Color = clLime; //sur fond noir c'est pas trop mal !
        //Récupérer la première valeur en y puis :
        int y = ...
        C->MoveTo(0,y);
        for(int x = 1; x < w; x++)
            {
            //Récupérer la valeur en y puis :
            y = ...
            C->LineTo(x,y);
            }
        //Effet 3D
        C->Pen->Color = clWhite;
        C->MoveTo(0,h); C->LineTo(0,0); C->LineTo(w,0);
        //Dessiner le bitmap en X,Y sur la form 
        Canvas->Draw(X,Y,Scope);
        }
    }
    A noter que si tu veux une représentation avec les valeurs positives se développant
    vers le haut, il faudra prévoir l'inévitable : y = axe - y; et ce pour les samples 16 bits
    qui curieusement sont signés (D'après ce que je sais, un DAC 16 bits n'a que faire
    du signe... mais bon... c'est comme ça !). Par ailleurs, l'ambitus d'un short est
    énorme par rapport à la hauteur d'un écran, et si l'on veut aller voir de plus près
    ce qui se passe au niveau d'une transition ou au point supposé du raccordement
    d'une alternance il vaut mieux se servir d'une deuxième fenêtre ! Sinon ça devient
    très vite très difficile à gérer pour l'utilisateur !

    Il faudra donc appeler cette méthode dans les OnPaint et OnResize de Form1.

    Dans la OnClose de Form1, ne pas oublier de détruire le bitmap :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    delete Scope;
    Scope = NULL; //au cas où et c'est ce qui explique le test dans la méthode !!!
    En faisant ainsi, il n'y a pas de scintillements (chez moi Pentium 233 MMX)!

    A plus !

  4. #4
    Membre Expert

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 407
    Par défaut
    Salut !

    Pour la deuxième question :

    Si tu veux générer une onde sinusoïdale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double pi = 3.14159265358979;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    signed short Sinusoidale[1024];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for(int j = 0; j < 1024; j++)
        {
        Sinusoidale[j] = 32767 * sin(pi * j / 512); //normalement 2 * pi * j / 1024
        }
    Comme ça ton signal est directement exploitable en wav.

    Pour d'autres formes d'ondes, prévoir les tableaux ad hoc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //--------Carré
    for (int j = 0; j < 512; j++)
        {
        Carre[j] = 32767;
        Carre[512 + j] = -32767;
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //--------Triangle
    for (int j = 0; j < 256; j++)
        {
        Triangle[j]=(signed short)(j * 127);
        Triangle[256+j]=(signed short)(32767 - (j*127));
        Triangle[512+j]=(signed short)(- (j * 127));
        Triangle[768+j]=(signed short)(-32767+ (j * 127));
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //--------Dent de scie
    for (int j = 0; j < 512; j++)
        {
        Rampe[j] = (signed short)(-32767 + (j * 64));
        Rampe[512+j] = (signed short)(j * 64);
        }
    Si tu veux générer un signal en fonction de l'onde et d'une fréquence, à partir de ces tableaux :

    Pour un échantillonnage à 44.1 Khz
    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
    // éventuellement rajouter un facteur zoom si le traitement est graphique sinon :
    double OndeStep = ((Frequence * 1024.0) / 44100.0) * 1.0; //1.0 pour montrer le zoom 
    //au départ le temps = 0 donc :
    double OndePos = 0; //accumule le temps qui passe en terme de fraction d'échantillon
    int OndeIndex = 0; //le temps qui passe en terme d'echantillon
     
     
    for(int x = 0; x < ...; x++)
        {
        OndeIndex = OndePos;
        signed short y = Sinusoidale[OndeIndex & 0x3FF]; //Tableau circulaire
        //s'il y a quelque chose à faire avec y alors c'est le moment...
        //...
        OndePos = OndePos + OndeStep; // prêt pour la fraction d'échantillon suivante
        }
    C'est vrai qu'avec cette méthode on a une distorsion du fait qu'a l'instant (t) il faudrait
    recalculer la valeur exacte de (y) sauf pour le signal carré, mais à l'oreille... !

    A plus !

  5. #5
    Membre très actif

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Par défaut
    télécharge ma source ici


    voila où j'en suis, c pas mal nan?
    enfin bof mais ça marche quand même pas mal, le plus gros probleme est comment faire pour afficher tous les points, sachant ke pour le moment il affiche 409points kel ke soit la taille du wav, 2ko ou 6mo....

    6mo jsui quand même assez content qu'il arrive à les "gérer"

    bon c prévu pour lire le signed 16bit avec débuts des vrais data à loctet 44, et ça ne cherche pas la fin des data (mais bon le probleme est d'afficher le spectre après, et vu que je n'en suis pas encore la....)

    a+ merci (quand même) de ta réponse

Discussions similaires

  1. Resize d'une image
    Par Anonymous dans le forum C
    Réponses: 6
    Dernier message: 13/07/2008, 22h23
  2. Lecture d'une image bitmap
    Par Geronimo dans le forum x86 32-bits / 64-bits
    Réponses: 18
    Dernier message: 28/06/2002, 12h01
  3. Réponses: 3
    Dernier message: 12/06/2002, 19h03
  4. lire une image au format RAW
    Par Anonymous dans le forum OpenGL
    Réponses: 5
    Dernier message: 20/05/2002, 00h11
  5. faire un selection dans une image aves les APIs
    Par merahyazid dans le forum C++Builder
    Réponses: 3
    Dernier message: 30/04/2002, 10h44

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