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 :

Ecriture du flux audio dans un fichier WAV


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Juin 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2010
    Messages : 38
    Points : 50
    Points
    50
    Par défaut Ecriture du flux audio dans un fichier WAV
    Bonjour,

    je suis actuellement entrain d'essayer de capturer le flux audio du périphérique par défaut (ici micro).

    Je stocke les données de capture dans un fichier temporaire et au moment de créer le fichier WAV je crée l'en-tête WAV et copie les données du fichier temporaire dans le fichier WAV.

    Mon problème est que je ne sais pas si l'écriture de l'en-tête et les données WAV sont correctes pour l'écriture du WAV.

    Actuellement je n'arrive pas à lire le fichier WAV avec Window Media Player.

    merci d'avance

    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
     
    #include <iostream>
    #include <ObjBase.h>
    #include <mmdeviceapi.h>
    #include <Audioclient.h>
    #include <Functiondiscoverykeys_devpkey.h>
     
    #include <ctime>
    #include <fstream>
     
    using namespace std;
     
    #define TMP_FILE "record.tmp"
     
    void writeWAVFile(const char* pathFile, WAVEFORMATEX *wfe, UINT32 sampleSize)
    {
    	int size;
    	char *buffer;
     
    	int chunkSize = sampleSize + 36;
    	int subChunkSize = 16;
    	int audioFormat = 1;
     
    	ofstream ofs(pathFile, ios::binary);
    	ofs << "RIFF";
    	ofs << reinterpret_cast<const char *>(&chunkSize);
    	ofs << "WAVE";
    	ofs << "fmt ";
    	ofs << reinterpret_cast<const char *>(&subChunkSize);
    	ofs << reinterpret_cast<const char *>(&audioFormat);
    	ofs << reinterpret_cast<const char *>(&wfe->nChannels);
    	ofs << reinterpret_cast<const char *>(&wfe->nSamplesPerSec);
    	ofs << reinterpret_cast<const char *>(&wfe->nAvgBytesPerSec);
    	ofs << reinterpret_cast<const char *>(&wfe->nBlockAlign);
    	ofs << reinterpret_cast<const char *>(&wfe->wBitsPerSample);
    	ofs << "data";
    	ofs << reinterpret_cast<const char *>(&sampleSize);
     
    	ifstream iTmp(TMP_FILE, ios::binary);
    	iTmp.seekg(0, ios::end);
    	size = iTmp.tellg();
    	iTmp.seekg(0, ios::beg);
     
    	if (size > 0)
    	{
    		buffer = new char[size + 1];
    		buffer[size] = '\0';
    		iTmp.read(buffer, size);
    		ofs << buffer;
     
    		delete[] buffer;
    		buffer = NULL;
    	}
     
    	iTmp.close();
    	ofs.close();
     
    	remove(TMP_FILE);
    }
     
    int main(int argc, char *argv[])
    {
    	// Begin program
    	IMMDeviceEnumerator *pEnumerator;
     
    	CoInitialize(NULL);
    	if (CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator) == S_OK)
    	{
    		IMMDevice *pDevice;
     
    		if (pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice) == S_OK)
    		{
    			IAudioClient *pAudioClient;
     
    			if (pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient) == S_OK)
    			{
    				WAVEFORMATEX *wfe;
    				pAudioClient->GetMixFormat(&wfe);
     
    				if (pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 10000000, 0, wfe, NULL) == S_OK)
    				{
    					IAudioCaptureClient *pAudioCapture;
     
    					if (pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pAudioCapture) == S_OK)
    					{
    						// Constants
    						const UINT timeout = (argc >= 3) ? (int)(argv[2] - '0') : 5;
    						const char* pathFile = (argc >= 2) ? argv[1] : "record.wav";
     
    						// Time
    						time_t startTime = time(NULL);
     
    						// Stream
    						ofstream ofs;
     
    						// Buffer capture
    						UINT32 packetSize;
    						BYTE *buffer;
    						UINT32 numFramesToRead;
    						DWORD flags;
     
    						// Infos capture
    						UINT32 sampleSize;
     
    						// Start capture
    						pAudioClient->Start();
     
    						while (true)
    						{
    							time_t now = time(NULL);
    							time_t interval = now - startTime;
     
    							if (interval >= timeout) break;
    							else
    							{
    								Sleep(32);
     
    								pAudioCapture->GetNextPacketSize(&packetSize);
     
    								while (packetSize != 0)
    								{
    									if (pAudioCapture->GetBuffer(&buffer, &numFramesToRead, &flags, NULL, NULL) == S_OK)
    									{
    										ofs.open(TMP_FILE, ios::binary | ios::app);
    										ofs << buffer;
    										ofs.close();
    										sampleSize += packetSize;
    									}
     
    									pAudioCapture->ReleaseBuffer(numFramesToRead);
    									pAudioCapture->GetNextPacketSize(&packetSize);
    								}
     
    								system("CLS");
    								cout << timeout - interval << endl;
    							}
    						}
     
    						// Ecrit les données dans le fichier WAV
    						writeWAVFile(pathFile, wfe, sampleSize);
     
    						pAudioClient->Stop();
    						pAudioCapture->Release();
    					}
    				}
     
    				pAudioClient->Release();
    			}
     
    			pDevice->Release();
    		}
     
    		pEnumerator->Release();
    	}
     
    	system("PAUSE");
    	return 0;
    }

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    voici la spec du format WAVE : https://ccrma.stanford.edu/courses/4...ts/WaveFormat/
    As-tu fait une comparaison entre les données attendues et celles que tu as ?
    As-tu essayé de charger un autre fichier pour le réenregistrer afin de valider ta fonction ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Juin 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2010
    Messages : 38
    Points : 50
    Points
    50
    Par défaut
    Salut,

    As-tu fait une comparaison entre les données attendues et celles que tu as ?
    Non, i a-t-il un moyen facile de comparer les données attendues avec celle que j'ai ? Sachant qu'au final je me retrouve avec un fichier .WAV que je peux éventuellement ouvrir au bloc-note.

    As-tu essayé de charger un autre fichier pour le réenregistrer afin de valider ta fonction ?
    Non, je n'ai pas pensé à cette possibilité. J'avais juste enregistrer un fichier WAV sur Audacity avec 5 secondes de silence sauf qu'il y a nettement plus de données sur le fichier d'audacity. De mon coté quand je n'ai pas de son, je n'ai pas de données tandis que sur audacity il y en a. Est-ce que se sont des données à blanc ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Il y a énormément de source d'erreurs possibles.
    Et tant que tu n'auras pas valider ta fonction ou les données sources, on ne va pas passer tout ton code en revue, il est bien trop gros.

    Regarde bien la spéc. Rien que sur l'ordre little/big-endian de chaque donnée il y a des confusions possibles.

    Oui même un blanc doit apparaître dans le fichier, s'il y a un blanc de 5s, ça doit se retrouver dans le fichier c'est évident.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Il faut gérer les silences :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
      {
          pData = NULL;  // Tell CopyData to write silence.
      }
    voir ici :

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    Ensuite, je ne connais pas très bien ofstream, mais certaines données doivent être écrites selon le format wave :

    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
     
     
     
    		ofstream ofs(pathFile, ios::binary);
    		ofs << "RIFF";
    		//ofs << reinterpret_cast<const char *>(&chunkSize);
    		//ofs << reinterpret_cast<const char *>(&chunkSize);
    		//ofs << reinterpret_cast<const char *>(&chunkSize);
    		ofs.write((char*)&chunkSize, 4); 
    		ofs << "WAVE";
    		ofs << "fmt ";
    		//ofs << reinterpret_cast<const char *>(&subChunkSize);
    		ofs.write((char*)&subChunkSize, 4); 
    		//ofs << reinterpret_cast<const char *>(&audioFormat);
    		ofs.write((char*)&audioFormat, 2); 
    		//ofs << reinterpret_cast<const char *>(&wfe->nChannels);
    		ofs.write((char*)&wfe->nChannels, 2); 
    		//ofs << reinterpret_cast<const char *>(&wfe->nSamplesPerSec);
    		ofs.write((char*)&wfe->nSamplesPerSec, 4); 
    		//ofs << reinterpret_cast<const char *>(&wfe->nAvgBytesPerSec);
    		ofs.write((char*)&wfe->nAvgBytesPerSec, 4); 
    		//ofs << reinterpret_cast<const char *>(&wfe->nBlockAlign);
    		ofs.write((char*)&wfe->nBlockAlign, 2); 
    		//ofs << reinterpret_cast<const char *>(&wfe->wBitsPerSample);
    		ofs.write((char*)&wfe->wBitsPerSample, 2); 
    		ofs << "data";
    		//ofs << reinterpret_cast<const char *>(&sampleSize);
    		ofs.write((char*)&sampleSize, 4);

  6. #6
    Membre du Club
    Profil pro
    Développeur Web
    Inscrit en
    Juin 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2010
    Messages : 38
    Points : 50
    Points
    50
    Par défaut
    Merci pour vos réponses je crois que je vais pouvoir m'en sortir grâce à vous

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Salut.
    Voici ce que je fait pour écrire un .wav. sout est ton ofstream ouvert en binaire. Data est le buffer audio.

    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
     
                    //FileBlocId
    		sout << "RIFF";
    		//FileSize
    		uint32_t fileSize = 36+data.size();
    		sout.write((char*)&fileSize,sizeof(fileSize));
    		//FileFormatID
    		sout<<"WAVE";
     
    		//FormatBlocId
    		sout<<"fmt ";
    		//BlocSize
    		uint32_t blocsize = 16;
    		sout.write((char*)&blocsize,sizeof(blocsize));
     
    		sout.write((char*)&audioFormat,sizeof(audioFormat));
    		sout.write((char*)&nbCanaux,sizeof(nbCanaux));
    		sout.write((char*)&frequence,sizeof(frequence));
    		sout.write((char*)&bytePerSec,sizeof(bytePerSec));
    		sout.write((char*)&bytePerBloc,sizeof(bytePerBloc));
    		sout.write((char*)&bitsPerSample,sizeof(bitsPerSample));
     
    		//datablocID
    		sout<<"data";
    		uint32_t dataSize = data.size();
    		sout.write((char*)&dataSize,sizeof(dataSize));
    		sout.write((char*)&data[0],data.size());
    Ps : Si tu est sous linux, il faudra penser à l'endian.

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

Discussions similaires

  1. ecriture d'un tableau dans un fichier
    Par hafid49 dans le forum C
    Réponses: 4
    Dernier message: 06/06/2006, 23h38
  2. Ecriture à une position donné dans un fichier
    Par xarius dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 29/05/2006, 16h05
  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. [Audio]Java et fichiers Wav
    Par danael dans le forum Multimédia
    Réponses: 3
    Dernier message: 10/10/2005, 20h09
  5. Réponses: 13
    Dernier message: 14/06/2003, 22h15

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