MOTEUR AUDIO TEMPS REEL AVEC GESTION DU VOLUME

Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
- - Dernière réponse : Phenixar
Messages postés
9
Date d'inscription
mardi 18 décembre 2001
Statut
Membre
Dernière intervention
27 avril 2007
- 27 avril 2007 à 16:46
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/41966-moteur-audio-temps-reel-avec-gestion-du-volume

Phenixar
Messages postés
9
Date d'inscription
mardi 18 décembre 2001
Statut
Membre
Dernière intervention
27 avril 2007
-
Salut,
je viens de voir ta nouvelle source pour le son.
mais j ai encore un soucis :p ... on ne peux pas choisir l'entrée ni la sortie
dans les 2 cas on se base sur ceux selectionnée par default dans windows
Je ne vois pas comment faire pour choisir une entrée bien precise ainsi qu'une sortie.
Si tu as un conseil n'esite pas.
merci.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Du coup naked ca marche sans problème aussi bien avec VC6 et Visual express c++ 2005
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
ah bien entendu, excuse mais c'est l'habitude qui fait croire évidentes des choses qui ne le sont pas forcément.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Petite précision quand même quant à l'utilisation de naked.

dans le fichier .h de déclaration de fonction il faut mettre:

int __fastcall copier_buffer(void * , void * , int);

et dans le fichier .cpp il faut mettre:

__declspec(naked) int __fastcall copier_buffer(void * dest, void * src, int taille)
{
__asm
{
...
...
}
}
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
Hors EAX, ECX et EDX qui sont considérés comme "écrasés", tous les registres sont à restaurer en sortie de fonction.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Pourquoi faut-il faire un push et pop de EBX a chaque fois ?
cs_arb
Messages postés
40
Date d'inscription
lundi 18 février 2002
Statut
Membre
Dernière intervention
5 novembre 2012
3 -
Super et très intéressant : le hic : je n'ai pas VCC. Puis je porter tout ça sous DEVCPP sans trop d'encombre ou un autre?
Merci de votre aide.
PS : je viens aussi de voir que tu as un gene de signal et je suis aussi super intéressé bricolant un peu d'électronique et d'interface PC. Est il aussi en VC?
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
Je répète: "rep movsd" et toutes autres formes de ces vieilles instructions de chaine sont totalement obsolètes, une boucle comme celle que je t'ai mise plus haut aura un rendement nettement supérieur, il est d'ailleurs aisé de dérouler la boucle pour minimiser le nbr de sauts de code:
lCPY:
mov eax, [edx]
add ecx, 4
add edx, 4
sub ebx, 1
mov [ecx], eax
jz short endCPY
mov eax, [edx]
add ecx, 4
add edx, 4
sub ebx, 1
mov [ecx], eax
jz short endCPY
mov eax, [edx]
add ecx, 4
add edx, 4
sub ebx, 1
mov [ecx], eax
jnz short lCPY
endCPY:
mov ebx, [esp-4]
ret 0

'naked' non reconnu sous VC6, bah je ne me souviens plus.
Pose donc VC++ 2005, son compilo est incomparablement meilleur:
http://www.cppfrance.com/code.aspx?ID=38359
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Apparemment VC6 ne connait pas naked, il dit que c'est "undeclared identifier".

Pour copier des DWORD on peut utiliser rep movsd ?



void copier_buffer(void * dest, void * src, int taille)
{
__asm
{
mov ecx, taille
shr ecx, 2
mov edi, dest
mov esi, src
cld
rep movsd
}
}
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
pas le temps de tout analyser, faudrait deja voir si tes CriticalSection sont utiles.

Pourquoi copier par WORD, en DWORD irait PLUS DE 2 FOIS plus vite.
Me seble que tu copies 4096 octets (meme 3eme param) à chaque appel.
En ce cas:
__decspec(naked) void __fastcall bnCopie4096(void *pdst, void *psrc)
{ // ECX pdst, EDX psrc
__asm { // 1204 tours de 4 octets = 4096
mov [esp-4], ebx
sub ecx, 4 ;// POUR PARALLELISATION DES INSTRUCTIONS
mov ebx, 1024
lCPY:
mov eax, [edx]
add ecx, 4
add edx, 4
sub ebx, 1
mov [ecx], eax
jnz short lCPY
mov ebx, [esp-4]
ret 0 ;// RIEN A DEPILER
}
}
ainsi aucun empilage de param.

Attention qu'on devrait garantir l'alignement des buffers sur un multiple de 4 sinon il y a une erreur d'alignement envoyée par le CPU.
OK sous Windows, c'est réglé par défaut pour que le système rattrape mais serait inacceptable pour du code haute performance.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Tu penses que memcpy() qui travaille avec des char est plus rapide que copier_buffer() avec des short ? Si c'est le cas je remplace la fonction.

Dans le zip il y a une fonction qui s'appelle filtrage.cpp mais qui est désactivée dans le code. Quand je l'inclus juste avant regler_volume() ça ralentit grave le traitement. Dois je ajouter un critical section dans le 2e Thread aussi ? Ai-je le droit d'utiliser la mm section critique pour les 2 Thread ?
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
Un bout d'ASM au milieu du code C gêne toute optimisation de la fonction.
On peut mettre de l'ASM mais alors on fait la fonction complète en ASM et on préfixe de __declspec(naked) indiquant au compilo de ne pas y toucher.
Je ne vois pas de modulo ici:
__asm // modulo
{
mov eax, wbi ; EAX = 0 au 1er tour
mov ebx, NB_BUFFER ; EBX = 3
inc eax
cmp eax, ebx ; if(++EAX < 3) goto fin1
jb fin1
xor eax, eax ; EAX = 0
fin1: mov wbi, eax

Tout ceci se réduisait à:
if(++wb1 < 3) goto fin1;
wbi = 0;
le compilo aurait épargné EBX.

copier_buffer() est du même genre, memcpy() direct dans le code gagnerait bien des cycles, pas d'appel de fonction. Ici tu en produis un tout en recopiant le code obsolète de ce bon vieux VC6, à ne jamais refaire.
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Quand tu dis que ce bout d'asm empeche le compilo toute optimisation tu parles du code entier ou juste de la fonction dans laquelle est ce bout d'asm ?
gabuzomeuh
Messages postés
53
Date d'inscription
jeudi 31 juillet 2003
Statut
Membre
Dernière intervention
28 mars 2007
-
Merci BruNews,

Je suis content que qqn s'intéresse à mon code.
Ce bout d'asm realise un modulo sur un popinteur qui augmente a chaque tout de Thread ça fait la mm chose que:

(wbi++ < NB_BUFFER-1) ? wbi : wbi=0

Ce que je cherche à faire c'est accélerer le traitement des 2 Thread car j'ai l'impression que les 2 Thread se marchent dessus de temps en temps.

Si j'augmente le nombre d'operations dans chaque Thread on finit par perdre des données ou est est-ce plutot à cause d'un mauvais verouillage des données ?
BruNews
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
13 -
__asm // modulo
{
mov eax, wbi
mov ebx, NB_BUFFER
inc eax
cmp eax, ebx
jb fin1
xor eax, eax
fin1: mov wbi, eax
}

Explication avec but à obtenir, svp.

Que vient faire ce bout d'asm dans une fonction en C ???
A part empêcher toute optimisation du compilo, je n'en vois pas la raison.
Se souvenir que EBX est à restaurer en sortie de fonction, tu forces donc le "push pop" au compilo.