Page 1 sur 1

Conversion de sons

Publié : jeu. 01/avr./2004 23:49
par ZapMan
Il me semble que je tiens une bonne colle pour les champions de PureBasic et des APIs :?: :
- Mon but est de réaliser un convertisseur de fichiers son. Je veux donc pouvoir ouvrir le fichier, le convertir et lui appliquer des effets, puis le ré-enregistrer.
- DirectSound permet d'ouvrir une grande variété de fichiers son (Wave, MP3, etc.) et permet aussi de leur appliquer des filtres (echo, flanger, etc.)
- La doc Microsoft explique assez bien comment mettre tout ça en oeuvre quand le but est d'envoyer le son final vers la carte son. Mais comment faire pour récupérer le résultat sous la forme d'un buffer mémoire lisible :?: . Comment accéder au ''Primary Buffer'' en lecture :?:
- J'ai commencé à explorer ACM (Audio Compression Manager) et je suis sur le point de pouvoir faire des décodage MP3->Wave avec ça, mais la plupart des filtres proposés par Microsoft ou des tierces parties sont conçus pour DirectX et ne semblent pas être accessibles à travers ACM.

J'ai déjà profité du travail de Danilo en exploitant son exemple nommé
''DirectX8_PlaySoundBuffer'' (CODEARCHIV).

C'est une question un peu pointue. Je la pose juste au cas l'un de vous se serait déjà pris la tête avec ça.
:wink:

Publié : ven. 02/avr./2004 1:43
par KarLKoX
J'ai déja fait un convertisseur en purebasic utilisant FMOD, elle permet de simplifier grandement ce que tu souhaites faire.
Mais si tu veux vraiement le faire toi même, il n'y a pas de réelles difficultés pour pouvoir convertire et appliquer tes effets.
Prenons le cas ou tu as un fichier wav que tu veux convertir en mp3 :
- tu initialises dsound, tes buffers et tes différentes variables,
- Pour récupérer un tampon de data, il faut utiliser la fonction Lock de ton objet LPDIRECTSOUNDBUFFER8 retourné par la fonction :

Code : Tout sélectionner

LPDIRECTSOUND8        SndSystem;
LPDIRECTSOUNDBUFFER    DadSndBuf;
LPDIRECTSOUNDBUFFER8	SndBuffer;

if (DirectSoundCreate8(NULL, &SndSystem, NULL) != DS_OK)
	return false;

if ((SndSystem->CreateSoundBuffer(&BufferDesc, &DadSndBuf, NULL)) != DS_OK)
		return false;

if ((DadSndBuf->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*) &SndBuffer)) != DS_OK)
		return false;
C'est du C mais c'est facilement compréhensible.

- A partir de la, tu peux utiliser les notifications de dsound ( cf LPDIRECTSOUNDNOTIFY et SetNotificationPositions) pour définir des fonctions callbacks qui seront appelées par dsound à certains moment (debut du buffer, millieu et fin),
- Dans chacune de ses fonctions (sauf celle du buffer de fin), tu peux enfin utiliser la fonction Lock de l'objet LPDIRECTSOUNDBUFFER8 et ainsi, tu peux faire tout ce que tu veux sur ce tampon avant d'appeler la fonction Unlock du même objet.
Dans le cas de l'encodage en mp3, il suffit de passer ce tampon à la fonction beEncodeChunk qui te retournera les données compressées en mp3. Idem pour les effets DSP, il faudra que tu te fasse une fonction qui prendra en paramettre ce tampons et qui le manipulera.
Voila en gros l'idée, j'ai du code en C si ca t'interesse qui utilise dsound 8 (mais impossible de compiler ma lib sonore avec purebasic des lors que j'utilise dsound ...).

Publié : sam. 03/avr./2004 2:27
par ZapMan
Wouahou !!

J'ai bien l'impression que j'ai trouvé mon champion !

Je pars en week-end et je n'ai pas le temps de creuser tes idées mais je m'y mets dès la semaine prochaine et il ya de fortes chances pour que j'ai encore besoin d'un petit coup de pouce.

Merci déjà pour tes tuyaux. Je savais que tu avais pas mal mis les doigts dans ces fonctions et j'avais l'espoir que tu pourrais me sortir de là.

Merci.

Publié : lun. 05/avr./2004 21:09
par ZapMan
Je suis preneur pour ton code C. Si c'est trop lourd pour être copier/collé, tu peux me le zipper à :

bleupiscines@lagoon.nc

Je m'en sors en C, mais aucun risque que je tombe définitivement dedans, comme c'est déjà arrivé tristement à l'un d'entre nous. Pour ma part, je crois que c'était vraiment idiot et je le penserai jusqu'à ce que quelqu'un puisse me prouver qu'on peut faire des choses en C qu'on ne fait pas avec Purebasic.

Publié : mar. 06/avr./2004 22:03
par KarLKoX
Plutôt que de te le mailer, je l'ai uploadé sur mon ftp histoire que d'en faire profiter un plus grand monde.
Tu peux consulter le code ici :)

Publié : jeu. 08/avr./2004 10:10
par ZapMan
Super ! Merci, t'es super.

Publié : sam. 10/avr./2004 16:25
par ZapMan
Bon, j'ai creusé ton code et les conseils que tu me donne et il me semble que quelque chose ne colle pas :
- Sauf erreur, DirectX fait ses transformations (compression, décompression, filtre, etc.) en prenant les données dans le secondary buffer, puis il stock le résultat dans le Primary Sound Buffer avant de les envoyer à la carte son.
- Les données que je veux récupérer sont donc dans le Primary.
- La fonction lock ne marche que pour le secondary et en plus elle ne marche que pour l'écriture, pas pour la lecture (c'est ce que dit la doc.)

D'autre part, dans ta réponse tu évoque un "beEncodeChunk" et je ne vois pas d'ou sort ce gugusse. :roll:

Tu aurais une piste ?

Publié : sam. 10/avr./2004 23:48
par KarLKoX
Oui, en fait il faudrait que tu fasses comme ca (on va dire que tu veux compresser du Ogg Vorbis en autre chose) :

- Tu initialise DirectX, la lib Ogg Vorbis, tes différentes variables, allocation mémoire (buffers, entre autre),
- tu te créé une fonction qui prendra en charge la lecture et une autre, l'écriture,
- Dans la fonction de lecture, tu feras appels aux fonctions de la bibliotheque Ogg Vorbis pour qu'il te retourne un tampon de données PCM via la fonction ov_read ou, si le Codec DirectShow est installé, tu demanderas à l'ACM de te remplir ce tampon (scéance de décodage)
- de la, tu averties (via les events ou autre méthode de synchronisation) que tu as un buffer de pres,
- La fonction d'écriture s'enclenche et la tu envoye ce tampon aux fonction de compression ACM (je m'y suis jamais interessé mais il y a surement une fonction dédié à ca)
- et ainsi de suite, jusqu'à la fin.

Bon, pour pas bouffer 100 % de cpu, il faudra faire un thread donc il faudra bien faire attention à l'acces de tes variables/tampons (utilise les mutex, cf les fonctions EnterCriticalSection/LeaveCriticalSection).
En esperant être compréhensible parce que j'ai du mal à expliquer par moment :)

PS : beEncodeChunk fait partie des fonctions de la partie DLL de Lame (regarde dans le répertoire DLL des sources de Lame, il y a une interface qui simplifie grandement l'utilisation de Lame)

Publié : dim. 11/avr./2004 1:49
par ZapMan
En esperant être compréhensible parce que j'ai du mal à expliquer par moment
Là, je sens qu'on partage une vibration.

Je vais essayer.