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 :

[Audio] Comment manipuler un fichier PCM [Non suivi]


Sujet :

C++Builder

  1. #1
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut [Audio] Comment manipuler un fichier PCM
    Salut,

    Voila je viens de faire mon acquisition, je voulais savoir comment je pourrais manipuler mon fichier PCM pour par exemple tracer ma courbe de frequence.

    comment il est structuré, ca je le sais, j'ai été jeter un coup d'oeil a cette adresse

    j'ai également chercher des info sur PCM, et je suis tomber sur RIFF. je me demande si c'est bien ceci que je dois utiliser. Je trouve ca assez compliqué.

    merci pour les infos.

  2. #2
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    je viens de lire la doc de RIFF et vola ce que je trouve :

    WAVEFORMATEX

    The extended wave format structure is used to defined all non-PCM format wave data, and is described as follows in the include file mmreg.h:

    /* general extended waveform format structure */
    /* Use this for all NON PCM formats */
    /* (information common to all formats) */
    typedef struct waveformat_extended_tag {
    WORD wFormatTag; /* format type */
    WORD nChannels; /* number of channels (i.e. mono, stereo...) */
    DWORD nSamplesPerSec; /* sample rate */
    DWORD nAvgBytesPerSec; /* for buffer estimation */
    WORD nBlockAlign; /* block size of data */
    WORD wBitsPerSample; /* Number of bits per sample of mono data */
    WORD cbSize; /* The count in bytes of the extra size */} WAVEFORMATEX;
    sachant que j'utilise waveformatex, ceci veut donc dire que le format du fichier que je recois n'est pas un fichier PCM ???? :

    Pour info j'ai trouvé quelques site sur le format PCM, ils parlent pratiquement tous de RIFF, ou de WAVEFORMATEX, par contre il ne disent rien sur la manipulation des données de ce fichiers.

    - MSDN
    - Université de Montpelier
    - freesoundeditor.com

  3. #3
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Salut Max,

    Au risque de répéter ce que tu sais déjà (n'ai-je rien d'autre à faire? ) ... RIFF est une classe de formats multimédia de Microsoft. Wave (extension .wav) est une sous-classe de RIFF pour l'audio, au format PCM généralement.
    Un fichier wave comprend un 'chunk' principal, et des chunks secondaires en nombre variables. Le 'chunk' n'est rien d'autre qu'une section.
    Dans le chunk principal en tête de fichier, tu trouveras trois infos:
    - l'identifiant RIFF
    - la taille du fichier
    - l'identifiant WAVE

    Normalement tu trouves ensuite le subchunk dit 'fmt ' (format). Ce chunk te donne toutes les infos relatives aux données audio: nombre de canaux, résolution, fréquence d'échantillonnage, taille du subchunk fmt etc... C'est lui qui est lu pour remplir la structure WAVEFORMATEX.

    Suivent normalement les données audio dans un subchunk dit 'data' (il commence par l'identifiant 'data'). Les données audio sont dans l'ordre pour un fichier mono, et alternées gauche-droite pour un fichier stéréo.

    Une fois que tu récupères tes données audio (dans un tableau par exemple), tu peux commencer à effectuer un traitement. Si tu veux une courbe du spectre des fréquences, tu vas probalement effectuer une FFT - c'est-à-dire que tu vas réaliser une opération mathématique complexe sur les données audio récupérées. Il te faut des notions de traitement du signal pour appliquer un tel traitement. Pour le reste tu vas trouver des routines FFT prêtes à l'emploi sur le net. J'ai même cru en voir une sur ce site.

    Voilà - je ne suis pas sûr de t'aider, mais ta question est très large...

  4. #4
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Citation Envoyé par kramer
    Salut Max,

    Au risque de répéter ce que tu sais déjà (n'ai-je rien d'autre à faire? ) ... RIFF est une classe de formats multimédia de Microsoft. Wave (extension .wav) est une sous-classe de RIFF pour l'audio, au format PCM généralement.
    Un fichier wave comprend un 'chunk' principal, et des chunks secondaires en nombre variables. Le 'chunk' n'est rien d'autre qu'une section.
    Dans le chunk principal en tête de fichier, tu trouveras trois infos:
    - l'identifiant RIFF
    - la taille du fichier
    - l'identifiant WAVE

    Normalement tu trouves ensuite le subchunk dit 'fmt ' (format). Ce chunk te donne toutes les infos relatives aux données audio: nombre de canaux, résolution, fréquence d'échantillonnage, taille du subchunk fmt etc... C'est lui qui est lu pour remplir la structure WAVEFORMATEX.

    Suivent normalement les données audio dans un subchunk dit 'data' (il commence par l'identifiant 'data'). Les données audio sont dans l'ordre pour un fichier mono, et alternées gauche-droite pour un fichier stéréo.

    Une fois que tu récupères tes données audio (dans un tableau par exemple), tu peux commencer à effectuer un traitement. Si tu veux une courbe du spectre des fréquences, tu vas probalement effectuer une FFT - c'est-à-dire que tu vas réaliser une opération mathématique complexe sur les données audio récupérées. Il te faut des notions de traitement du signal pour appliquer un tel traitement. Pour le reste tu vas trouver des routines FFT prêtes à l'emploi sur le net. J'ai même cru en voir une sur ce site.

    Voilà - je ne suis pas sûr de t'aider, mais ta question est très large...
    Je ne pense pas qu'elle soit si large que ca ... en fait je sais que j'ai mon header de mon fichier PCM, mais je ne sais pas a partir d'où les données se trouvent, et comment le savoir.

    en fait je veux appliquer une FFT derriere et j'ai besoin de récupérer ces données... si ce n'était que pour de la lecture ca ne poserais pas de probleme, je n'aurrais pas besoin de me préoccuper de savoir comment sont structurés les fichier PCM....

    Malheureusement j'ai besoin de tout ca.. bref pour résumer

    - je sais comment sont structurer les fichiers PCM
    - je sais que les données ce trouve a un certain endroit dans mon fichier
    - je ne sais pas comment savoir où ces données commencent, et où elle finnissent (et oui on peut avoir des chunk a la fin du fichier, donc ca fait pas parti des données)
    - j'ai vu une variable qui s'appel "ckID[4]" et a coté c'est marqué DATA
    ==> moi je ne suis pas difficile, j'en déduis que c'est les données, problème : c'est quoi ce tableau de 4 lignes ???

    Donc voila après une journée entière de recherche je ne suis toujours pas plus avancé, ça m'agace .... j'ai l'impression de rien faire ... si seulement je trouvais ca ... après ca irais vite ...

    Merci a tous ceux qui ont jeté un coup d'oeil a ce post... et Merci d'avance a tous ceux qui vont le faire, et peut etre m'aider

  5. #5
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Pour récupérer tes données:
    1. Tu localises le subchunk 'data'
    2. Tu avances ton pointeur de 4 positions ('data' occupe 4 octets)
    3. Tu lis la taille occupée par les données. Cette info se situe juste après 'data', et est donnée en octets. Le nombre est codé en integer 32 bits sauf erreur.
    4. En fonction de la résolution et du nombre de canaux, tu peux calculer le nombre d'échantillons à lire (voir subchunk 'fmt ').
    5. Les données audio sont à la suite.
    6. Les autres subchuncks, tu peux les jeter, ils sont facultatifs.

  6. #6
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Citation Envoyé par kramer
    Pour récupérer tes données:
    1. Tu localises le subchunk 'data'
    2. Tu avances ton pointeur de 4 positions ('data' occupe 4 octets)
    3. Tu lis la taille occupée par les données. Cette info se situe juste après 'data', et est donnée en octets. Le nombre est codé en integer 32 bits sauf erreur.
    4. En fonction de la résolution et du nombre de canaux, tu peux calculer le nombre d'échantillons à lire (voir subchunk 'fmt ').
    5. Les données audio sont à la suite.
    6. Les autres subchuncks, tu peux les jeter, ils sont facultatifs.
    justement ..... comment je fais tout ca ... j'en ai aucune idée ...

  7. #7
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Tu utilises les fonctions classiques de manipulation de fichiers binaires. En C Ansi: fopen, fread, fclose, fread, fseek, fwrite.
    Sous Windows/Builder, tu as sans doute des fonctions plus appropriées. D'autres membres pourront peut-être te renseigner.

  8. #8
    Membre chevronné

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 386
    Points : 1 772
    Points
    1 772
    Par défaut
    Salut !

    A mon avis, les fichiers wave au format WAVE_FORMAT_PCM ne sont pas dotés de subchunk laissant
    apparaître plusieurs tronçons audio distincts dans le fichier.

    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
    class TFileWaveHeader
    {
    public :
    char RiffID[4];
    int Riffsize;
    char WaveID[4];
    char FmtID [4];
    unsigned int Formatsize;
    unsigned short FormatTag;
    unsigned short nChannels;
    unsigned int nSamplesPerSec;
    unsigned int AvgBytesPerSec;
    unsigned short BlockAlign;
    unsigned short BitsPerSample;
    char DataID[4];
    unsigned int DataSize;
    //...les données commencent ici... dans ce qui va suivre ...
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Byte *Buffer; // on charge le fichier dans un tableau... par exemple !
    Donc pour accéder aux paramètres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TFileWaveHeader *FWH = (TFileWaveHeader*)Buffer;
    Le header fait 44 octets. Si le fichier était stocké en mémoire, les données commenceraient
    donc dans le buffer, juste après le header, selon que :

    Si le FWH->avgBitsPerSample vaut 8 (8 bits = 1 Byte, car ici les données ne sont pas signées)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Byte *Echantillons = &Buffer[44];
    Sinon le FWH->avgBitsPerSample vaut 16 (16 bits = 1 short, car ici les données sont signées)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short *Echantillons = &Buffer[22];
    Ensuite, l'extraction des canaux dépend de la valeur de FWH->nChannels.

    Si FWH->nChannels vaut 1, alors le signal audio est mono.
    Dans ce cas, les données sont de facto consécutives.

    Si FWH->nChannels vaut 2, alors le signal audio est stéréo.
    Dans ce cas, les canaux L et R (Byte ou short selon que...) sont entrelacés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //échantillons à l'instant t
    L = *Echantillons; Echantillons++;
    R = *Echantillons; Echantillons++;
    //échantillons ) l'instant t + 1
    L = *Echantillons; Echantillons++;
    R = *Echantillons; Echantillons++;
    A plus !

  9. #9
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    merci je test et je vous fait signe ....

    --------------------------------------------------------------

    Je viens de tester vite fait ... ca à l'air de le faire, merci énormément henderson pour tout ce que tu as fait pour m'aider, je vous tiens au courant après des test plus poussés

  10. #10
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Bon alors j'obitiens bien des données, mais comment savoir si ces données ne sont pas aléatoires, enfin comment etre sur de l'intégrité de ces données ??

    Merci

  11. #11
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    j'ai une autre remarqu. Lorsque je récupère ces données, je n'ai aucun chiffre négatif.

    si j'affiche mon échantillon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    Byte *Echantillons = &Buffer[44];
     
    for (i = 0; i < SizeBuffer ; i++)
    {
    LBl_test->caption=(AnsiString)Echantillon[i];
    }
    voila, en gros c'est ce que je fait dans mon programme, mais c'est dans une list (j'affiche les valleur de mon buffer (c'est juste pour les tests)).

    bref, je n'est aucune valeur inférieur a zéro, alors je me demande s'il ne faut pas que je cast les échantillons ????

  12. #12
    Membre chevronné

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 386
    Points : 1 772
    Points
    1 772
    Par défaut
    Salut !

    Le type Byte correspond au type unsigned char.
    C'est le format 8 bits qui est donc non signé comme je l'ai indiqué dans une réponse précédente.

    Le format 16 bits (du type short) est par contre signé.

    A plus !

  13. #13
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Citation Envoyé par henderson
    Salut !

    Le type Byte correspond au type unsigned char.
    C'est le format 8 bits qui est donc non signé comme je l'ai indiqué dans une réponse précédente.

    Le format 16 bits (du type short) est par contre signé.

    A plus !
    pardon, je croyais que le type short c'était pour le format stéréo, j'avais pas fait gaff ... autant pour moi, vais essayer ca de suite ???

  14. #14
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    tu as dit qu'il faut utiliser le short lorsque nAvgBytesPerSec=16, mais :

    on sait que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    nAvgBytesPerSec = nSamplesPerSec * nBlockAlign;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    nBlockAlign = (nChannels * wBitsPerSample) / 8
    or moi en l'occurrence j'échatnillon a 44100 Hz, donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    nBlockAlign = (1 * 8) / 8 = 1
    et donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    nAvgBytesPerSec = nSamplesPerSec * nBlockAlign
     
    nAvgBytesPerSec = 44100 * 1 = 44100
    et aucun cas je n'obtien 16 pour nAvgBytesPerSec, meme si j'échatillone en 16 bits.
    peut etre tu t'es trompé de variable ???

    Merki

  15. #15
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Citation Envoyé par henderson
    Donc pour accéder aux paramètres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TFileWaveHeader *FWH = (TFileWaveHeader*)Buffer;
    Le header fait 44 octets. Si le fichier était stocké en mémoire, les données commenceraient
    donc dans le buffer, juste après le header, selon que :

    Si le FWH->avgBitsPerSample vaut 8 (8 bits = 1 Byte, car ici les données ne sont pas signées)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Byte *Echantillons = &Buffer[44];
    Sinon le FWH->avgBitsPerSample vaut 16 (16 bits = 1 short, car ici les données sont signées)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short *Echantillons = &Buffer[22];

    voila alors moi j'ai fait ceci pour commencer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Byte *buffer = smple.getBuffer();
    pcm = (formatWave*)buffer;
    Byte echantillons = &buffer[44];
    ca ca fonctionne très bien, enfin ca compile et ca tourne, après les valeurs qu'il sort j'en sais rien, bref...

    bon j'essaye de remplacer Byte par short :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Byte *buffer = smple.getBuffer();
    pcm = (formatWave*)buffer;
    short echantillons = &buffer[22];
    et la il me sort une erreur :

    Ipossible de convertir 'unsigned char *' en 'short *'
    Pour info la procedure getBuffer() de smple renvoi mon buffer de type PBYTE.

    Merci de votre aide....

  16. #16
    Membre chevronné

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

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 386
    Points : 1 772
    Points
    1 772
    Par défaut
    Salut !

    C'est vrai, c'est une erreur au niveau rédaction mais....

    avgBitsPerSample pour wBitsPerSample !

    mais certainement pas BytesPerSec (confusion avec le avgBytePerSec) qui n' a rien à faire ici !

    On a juste besoin de deux paramètres pour le traitement :
    - le nombre de canaux nChannels 1 ou 2
    - la définitiion de l'échantillonnage wBitsPerSample 8 ou 16

    Si 8 bits alors le type du pointeur est bon (LPBYTE == Byte*)
    Si 16 bits alors il faut transtyper :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short *S = (short*)...;
    Ne pas oublier que les canaux Gauche et Droit d'un signal stéréo sont entrelacès !

    A plus !

  17. #17
    Membre averti Avatar de max44410
    Étudiant
    Inscrit en
    Juin 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2003
    Messages : 426
    Points : 301
    Points
    301
    Par défaut
    Merci encore je regarde ca et je vous tiens au courant

Discussions similaires

  1. Comment manipuler des fichiers binaires ?
    Par yrejk dans le forum C++
    Réponses: 1
    Dernier message: 15/04/2008, 19h40
  2. [CSV] Comment manipuler un fichier csv ?
    Par gorgoroth dans le forum Langage
    Réponses: 5
    Dernier message: 20/03/2008, 22h35
  3. Comment manipuler plusieurs fichiers Excel
    Par Olivier0 dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 16/08/2007, 08h38
  4. [débutant]comment manipuler des fichiers bitmap
    Par caty_info dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 04/04/2007, 10h20
  5. Réponses: 8
    Dernier message: 26/08/2006, 01h22

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