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++ Discussion :

problème écrire wave avec libsndfile, part2.


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut problème écrire wave avec libsndfile, part2.
    Bon,


    j'ai un petit problème avec mon prog qui est censé lire un fichier wav et le ré-écrire dans un autre dossier (je me suis inspiré de http://loulou.developpez.com/tutorie...al/capture/#L2) :

    mon Track.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
     
    class Track{
     
    	public:
    		Track ();
    		sf_count_t  frames;
    		int samplerate;
    		int channels;
    		int format;
    		int sections ;
    		int seekable ;
    		int SizeOfWav;
    		const char* path;
    		SF_INFO FileInfos;
    		SNDFILE * File;
    		vector<float> Samples();
     
    Track::Track(const char* INPUT);
    };

    mon Track.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
     
    Track::Track(const char* INPUT){
     
    	SF_INFO FileInfos;
    	SNDFILE * File;
     
    //ouverture et lecture infos Wav
     
    	File = sf_open(INPUT, SFM_READ, &FileInfos);
     
        if (!File)
    		cout << "pas de fichier" <<  endl;
     
    	int *psamplerate=&samplerate;
    	int *pformat=&format;
    	int *pchannels=&channels;
    	sf_count_t  *pframes=&frames;
     
    	*psamplerate=FileInfos.samplerate;	
    	*pformat=FileInfos.format;
    	*pchannels=FileInfos.channels;
    	*pframes=FileInfos.frames;
     
     
    //vecteurs de samples
     
    	int SizeOfWav = *pframes-1;	
    	vector<float> Samples(SizeOfWav); 
    	sf_read_float(File, &Samples[0], SizeOfWav);
     
    	sf_close(File);
    }
     
     
    void Track::WriteFile(Track INPUT){
     
     
    	sf_count_t   z;
    	const char* path= "/Users/chercheur/Desktop/Projets/Soundlab/test/testout.wav";
     
    	int *psamplerate=&samplerate;
    	int *pformat=&format;
    	int *pchannels=&channels;
    	sf_count_t *pframes=&frames;
     
    	FileInfos.samplerate = *psamplerate;
    	FileInfos.format = *pformat;
    	FileInfos.frames = *pframes-1;
    	FileInfos.channels = *pchannels;
     
     
    	SNDFILE*  FileOut = sf_open(path, SFM_WRITE, &FileInfos);
        if (!FileOut)
            return;
     
    	FileInfos.samplerate = *psamplerate;
    	FileInfos.format = *pformat;
    	FileInfos.frames = *pframes-1;
    	FileInfos.channels = *pchannels;
     
    // écriture wave
     
    	int SizeOfWavout = *pframes);	
    	z=sf_write_float(FileOut, &INPUT.Samples[0], SizeOfWavout);
        sf_close(File);
    }
    mon main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int main ()
    {
     
    	Track Wav("/blablat/test2.wav");
    );
     
    WavOut("/blablabla/testout.wav");
    	WavOut.WriteFile(Wav);
     
    return 0;
    }
    résultat, j'ai une erreure (pour la partie écriture, la lecture fonctionne) :


    162: error: invalid types '<unknown type>[int]' for array subscript

    sur la ligne : z=sf_write_float(FileOut, &INPUT.Samples[0],SizeOfWavout);

  2. #2
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Citation Envoyé par ostralo Voir le message
    résultat, j'ai une erreure
    Mon dieu... ca fait mal ??

    Bon et si tu essaye comme ça : &(INPUT.Samples[0]) ?

  3. #3
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut
    Citation Envoyé par NiamorH Voir le message

    Bon et si tu essaye comme ça : &(INPUT.Samples[0]) ?
    pas mieux mais, en fait en déclarant

    vector<float> Samples;
    au lieu de:

    vector<float> Samples();
    ça compile, par contre, toujours pas de fichier ré-écrit correctement.

    sur quelques points :

    int i;
    for (i=5000; i<5005; i++)
    cout << i << ": " << INPUT.Samples[i]<< endl;
    donne :

    5000: 0
    5001: 0
    5002: 0
    5003: 0
    5004: 0

    normalement : ça devrait (fichier source):

    5000: -0.00341797
    5001: -0.00338745
    5002: -0.00177002
    5003: -0.00170898
    5004: -0.000640869
    donc forcement, fichier vide en sortie...

    Une idée?

  4. #4
    Invité
    Invité(e)
    Par défaut
    ostralo,

    Regarde bien ton constructeur: ton tableau Samples qui reçoit les données sources est une variable locale, qui disparaît aussi tôt ton constructeur fini. Perdu les samples, il est normal que tu ne réécrives que des zéros dans le fichier résultat.

    Ce qu'il te faut faire, c'est dimensionner Samples correctement, pas le redéclarer localement.

    Par contre, à titre d'exercice, explique-moi à quoi servent tous ces pointeurs int* que tu utilises par batteries entières.

    Cheers,

    Carl

  5. #5
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut
    ...pour les pointeurs, je voulais juste tester mais ça n'a pas forcement d'utilité ( je débute !). Pour le vecteur de Samples, je comprends le problème mais j'avoue que je ne vois pas trop comment faire pour avoir accés à ces données partout dans mon programme?

    Citation Envoyé par 5hdumatin Voir le message

    Ce qu'il te faut faire, c'est dimensionner Samples correctement, pas le redéclarer localement.

    Carl
    je comprends pas trop la manip?

    merci par avance!

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Tu devrais peut-être utiliser le wrapper C++ pour libsndfile, soit SndfileHandle ?
    (cf. sndfile.hh)

    MAT.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut
    Citation Envoyé par Mat007 Voir le message
    Salut,

    Tu devrais peut-être utiliser le wrapper C++ pour libsndfile, soit SndfileHandle ?
    (cf. sndfile.hh)

    MAT.

    ...euh ??

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Citation Envoyé par ostralo Voir le message
    ...euh ??
    Si tu veux dire 'pourquoi ?' : parce que ça permet de faire du RAII et que ça donne souvent du code plus simple.
    Si tu veux dire 'ça va régler mon problème ?' : en effet non sans doute pas mais ça ne peut pas faire de mal.
    Si tu veux dire 'de quoi tu parles ?' : il y a un wrapper C++ de fourni avec libsndfile, il se trouve dans sndfile.hh.

    Si tu veux dire autre chose, désolé je n'ai pas réussi à le deviner...

    MAT.

  9. #9
    Membre actif
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Points : 216
    Points
    216
    Par défaut
    concernant Sample (le vector) : il est deja déclaré comme membre de la classe. Donc accessible par le constructeur. Le fait de redéclarer un vecteur Sample dans le constructeur fait que tu crées un AUTRE vector Samples, local au constructeur, qui empeched'accéder au vector Sample de la classe (car il a le meme non.

    Il ne faut tout simplement pas déclarer vector sample dans le constructeur.

    Si tu as besoin de la ligne :

    vector<float> Samples(SizeOfWav);

    Pour le redimensionner, utilises la fonction resize de vecteur. (Samples.resize(SizeOfWav); ou un truc du genre. )

  10. #10
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut
    ....bon j'utilise une solution intermédiaire (que j'aime pas trop) possiblement dangereuse : je déclare mon vecteur en variable globale comme suit :

    using namespace std;

    vector<float> Samples;

    Track::Track(const char* INPUT){
    ...

    ...


    }
    et là c'est OK. En attendant de tester autre chose,

    votre avis sur cette solution?
    merci pour vos conseils!

  11. #11
    Invité
    Invité(e)
    Par défaut
    Coin coin! Mauvaise idée. Si nous te laissons prendre ce genre d'habitudes, on risque de nous en vouloir par la suite...

    Reviens à ta définition de départ. Tu as une classe avec un membre de type vector<float> qui s'appelle Samples:
    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
     
    class Track
    {
      vector<float> Samples;
     
      // ...
     
      Track()
      {
        // ...
        int SizeOfWav = *pframes-1;	
        vector<float> Samples(SizeOfWav); // FAUX: Un nouveau vecteur temporaire...
        Samples.resize(SizeOfWav);  // OK: Le membre "Samples" de ta classe 
        sf_read_float(File, &Samples[0], SizeOfWav);
      }
     
     
      const vector<float>& GetSamples() const
      {
        return Samples;
      }
    }
    Jette un oeil au constructeur: j'ai mis ta ligne d'origine, et une correction proposée. Tu vois la différence entre les deux?

    Bon, maintenant que tu as bien stocké les samples dans ton objet, il faut pouvoir y accéder pour les recopier dans un autre objet. Pour cela, je te propose la méthode "GetSamples()" qui renvoie une référence en lecture seule vers le tableau de samples de ton objet de départ.

    Tu peux deviner la suite?

    Carl

  12. #12
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Salut, je suis sur le même code, je m'imice dans la discussion donc...
    Pourquoi déclarer sample en pointeur ?

    et pourquoi un const ?

    A moins que ce ne soient les adresses mémoires qui sont const ?

    Ca va pas créer des problèmes de push_back, etc ?

    Merci

  13. #13
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    et une autre question à propos de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     sf_read_float(File, &Samples[0], SizeOfWav);
    on peut appeler GetSample là dedans ou pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     sf_read_float(File, GetSamples[0], SizeOfWav);
    J'imagine que non, alors pourquoi un getter ?

    Je commence à peine à entrevoir l'intérêt des gestions de pointeurs etc, avec ostralo qui les adore en plus , mais je ne comprends pas cette déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      const vector<float>& GetSamples() const
      {
        return Samples;
      }
    Pourquoi un & ? C'est plutot :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      const vector<float>& GetSamples() const
      {
        return &Samples;
      }

  14. #14
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    pour exemple voii ma classe :

    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
    class Track {
    	public:
     
    	const char* path;
    	SNDFILE* File;
    	SF_INFO FileInfos;
    	const vector <float>& sample;
     
    	public:
    	Track::Track ();
    	Track::Track (const char* SOURCE);
    	Track::Track(const char* SOURCE, int C, int S, int F);
     
    	void Track::info ();
    	void Track::setSample();
    	const vector<float> Track::getSample();
     
    	void Track::copy (Track copiedFile);
    	void Track::replace (Track originFile, int frameIN, int frameOUT);
    	void Track::mix (Track originFile);
     
     
    };
    un constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	
    	Track::Track (const char* SOURCE){   ///load en existant track
    		
    		this->path=SOURCE;
    		// Ouverture du fichier audio avec libsndfile
    		///read infos
    		this->File = sf_open(path, SFM_READ, &FileInfos);
    		if (!File)   
    			this->File = sf_open(path, SFM_WRITE, &FileInfos);
    		this->setSample();
    	}
    (on peut appeler une méthode dans un constructeur ? héhé)

    et les méthodes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    	const vector<float> Track::getSample (){
    		return sample;	
    	}
     
    	void Track::setSample (){
    		sf_count_t S;
    		this->sample.resize(FileInfos.frames*FileInfos.channels);
    		S = sf_readf_float(this->File, &sample[0], this->FileInfos.frames);
    		cout << S << " frames mise en mémoire sur " << this->FileInfos.frames << " frames." <<endl<<endl;
    	}

  15. #15
    Nouveau membre du Club
    Inscrit en
    Janvier 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 63
    Points : 38
    Points
    38
    Par défaut
    OK, merci à toi, 5hdumatin pour tes conseils, effectivement, c'est plus élégant comme ça!

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    ttone: Ce que tu sembles ne pas comprendre, c'est le principe des références en C++.
    Une référence n'est absolument pas la même chose qu'un pointeur.

  17. #17
    Invité
    Invité(e)
    Par défaut
    ttone, laisse-nous répondre avant de saturer le forum! :-)

    J'ai relu le code posté au départ, et effectivement, le "getter" n'est pas indispensable, surtout comme je l'ai écrit. Il aurait été plus intéressant si une autre classe avait eu besoin d'accéder aux samples, ce qui n'est pas le cas dans le code posté.

    Ah! et puis mettez-vous aussi d'accord tous les deux sur le vocabulaire: "sample" veut dire une chose chez l'un, une autre chez l'autre. Pour toi, "sample" semble vouloir dire "son" (par exemple un sample de 12 secondes lu depuis un fichier) alors que ton collègue ostralo utilise "sample" pour dire "échantillon", l'unité de base de l'audio numérique, assez petit (entre 16 et 64 bits en général) et dont il te faut 44100 pour coder une seconde de son sur un CD par exemple.

    Le code posté utilise la sémantique d'ostralo. C'est peut-être pour cela que tu ne comprends pas pourquoi utiliser tel ou tel type.

    Carl

  18. #18
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Merci 5hdumat, ma sémantique est la même qu'ostralo, pas de problme a ce niveau, je vais regarder le principe des référence un peu plus en détail. Je voyais ca comme un pointeur... plus simplement, ca m'étonne qu'une méthode de libsndfile appelle &sample, au lieu de sample tout simplement... je m'y attarde

  19. #19
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    mais avant de m'intéresser aux références, pourquoi y a pas un conflit entre la déclaration de la méthode et ce qu'elle retourne dans ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const vector<float>& GetSamples() const
      {
        return Samples;
      }

  20. #20
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Si Samples est un vecteur de float, non: La fonction membre retourne juste une référence const vers ce vecteur.

Discussions similaires

  1. Problème de mémoire avec BDE
    Par Machuet dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/07/2004, 10h11
  2. problème de requête avec jointures
    Par tinhat dans le forum Requêtes
    Réponses: 7
    Dernier message: 11/08/2003, 10h33
  3. Problème dans requête avec count()
    Par BadFox dans le forum Requêtes
    Réponses: 3
    Dernier message: 08/07/2003, 18h02
  4. [Kylix] problème compilation kylix3 avec redhat 9.0
    Par madininaoursa dans le forum EDI
    Réponses: 1
    Dernier message: 02/07/2003, 16h21
  5. Problèmes de versions avec Xalan, Xerces et Java
    Par honeyz dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 05/06/2003, 10h18

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