STREAMER DU SON EN VB SUR WINMM ET WINSOCK...

cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 - 25 févr. 2003 à 19:54
cs_epson1 Messages postés 89 Date d'inscription dimanche 12 novembre 2000 Statut Membre Dernière intervention 29 mars 2013 - 20 oct. 2005 à 20:48
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/6255-streamer-du-son-en-vb-sur-winmm-et-winsock

cs_epson1 Messages postés 89 Date d'inscription dimanche 12 novembre 2000 Statut Membre Dernière intervention 29 mars 2013
20 oct. 2005 à 20:48
Hexanium ,Merci .
J'ai mis deux jours pour digérer tes explications et d'un coup j'ai vu la lumiére !!!
Puissant raisonnement ,je crois que j'ai compris et je m'en vais de suite faire des essais .Suis pas trés fort en math mais je dois pouvoir m'en sortir .Encore un grand merci pour ton aide ,et bon rétablissement .
(Y te reste pas un doliprane ?... ;) je vais en avoir besoin)
A++
hexanium Messages postés 32 Date d'inscription mercredi 20 avril 2005 Statut Membre Dernière intervention 26 septembre 2005
11 oct. 2005 à 17:25
Salut,

Bon je vais peut etre dire des conneries, (j'ai la creve et ma au crâne) mais voila comment je le vois:



sur cette image c'est un peu l'erreur qu'il faut pas faire mais la facon de voir doit marcher.
Je m'explique:

-Déja il faut apprendre a configurer correctement Winmm, (dans le module du source ici c dans la fonction OpenIn() ) C'est ici qu'on parametre le device, Mono/Stereo echantillonage, etc...
Ici apparament il te faut du stereo.
(regarde ici http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveform_functions.asp)


-L'idée c'est de générer a l'initialisation de l'appli les tableaux des données a mettre sur la sortie de la carte. Les valeur de ces tableaux sont les valeur de tes sinus.
Il te faut 2 tableaux (1 pour chaque voies), il faudra calculé la taille de ce tableaux judicieusement (en rapport avec la frequence d'echantillonage). Ton appli fera en permanance alimenter les buffer Winmm a partir de ces 2 tableaux pré calculés.
(Tu imagine donc 1 index qui parcour le tableau et si il arrive au bout il recommence au debut.)
Pareille pour les 2 voies !
Bien sur tu aura tous de suite pigé que les 2 index n'irons pas à la meme vitesse puisque ce sont 2 fréquences differentes

Tu peux donc voir que la subtilité se trouve dans le choix de la frequence d'echantillonage et des valeurs du tableau.


Déja prenons l'exemple du graphique au dessus.
Ici j'ai paramétré la carte en 8000 Hz, j'ai donc 1 échantillon toute les 125µs. Pour pouvoir faire une sinus de 1Khz avec ca, j'ai besoin de 8 echantillons du buffer. je reperterais ces echantillons indéfiniment, on aura alors du 1000 Hz. (la sinusoide aurra une sale gueule (8 echantillons seulment, c pas trop le probleme, le plus embetant encore c'est que la precison à "l'echantillon" pour décaller le signale.
si on déclale d'un echantillon on a lors soit 1/1.125ms=888hz ou 1/875µs=1142 Hz
on est loin des 1000 Hz + ou - 4Hz
Il faut plus d'échantillons !!!

Il faut donc que tu trouves par calcul ou empiriquement la frequence d'echantillonage dont tu as besoin. Ensuite prend un papier, une calculatrice ou excel et calcul les valeurs de tes 2 sinus pour remplire les tableaux

En gros il faut des périodes de 996 µs à 1004 µs donc la precision est de 4µs. C'est a dire qu'il faut es echantillons de taille max de 4µs
Si je dit pas de connerie: 1/4ms = 250 Khz.

Je sais pas si tu peux echantilloner à 256 Khz sur ta carte audio mais ca serait déja un certain niveau de précision .

Bien sur une fois le system compris il serait préferable de pouvoir calculer automatiquement à l'initialisation ou de pouvoir recalculer les valeurs des tableaux de sinus en fonction de la frequence ou du décalage spécifié par l'application.

Bref j'espere que j'ai aps raconté trop de bétise et que tu as pigé le principe, mais c'est tout a fait faisable en VB avec ce bout de code source.

Vais me prendre un doliprane ;)...

Hexanium
cs_epson1 Messages postés 89 Date d'inscription dimanche 12 novembre 2000 Statut Membre Dernière intervention 29 mars 2013
10 oct. 2005 à 17:02
Salut Ludolpif et Hexanium , et merci de me répondre aussi rapidemment pour m'aider .
En fait j'ai besoin d'un prog qui produise deux signaux sinusoïdaux(gauche et droite) dont la fréquence doit être d'environ 1000 HZ (pas critique) mais avec un ecart de 4 HZ(précis) entre les deux.
Pour l'instant, j'ai réussi à produire une sinus à gauche et une rampe à droite simultanément en remplissant un buffer directx.
(modif de cette source :http://www.vbfrance.com/code.aspx?ID=25409 de RDX ,ça m'a parru semblable dans le fonctionnement à WinMM)
Mais je sais pas comment produire deux sons de féquences différentes.Voila, je suis coincé là ...
Si qq a une idée je suis preneur et en plus ça me permet d'apprendre vu que je suis encore relativement novice en VB (je m'y suis mis y'a un peu plus d'un an, mon boulot c'est plus l'electronique)
Encore un grand MERCI pour vôtre aide et au plaisir de vous lire .
Cordialement .
hexanium Messages postés 32 Date d'inscription mercredi 20 avril 2005 Statut Membre Dernière intervention 26 septembre 2005
8 oct. 2005 à 12:51
Saluté les Amigos, (c grosiflex)
Pour plus d'info sur WinMM mattez ici:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveform_functions.asp

Ensuite regardez une source avec par exemple SndPlaySound en VB, retgardez bien le prototype C du MSDN et le Prototype VB trouvé pour SndPlaySound, vous ne devrier pas avoir de mal à creer tous les prototypes VB pour toutes les fonctions Winmm. (dans ma source y'a déja une petite partie des prototypes)

A++

Hexanium (Alias Grosiflex)
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
7 oct. 2005 à 15:44
heu... Je me rappelle plus trop de WinMM même si à une époque j'ai + ou - dû m'en servir, mais je tenai à t'avertir d'1 truc EPSON1 : si tu fais 1 échantillonneur de fréquences... fais gaffe aux conséquences du fait que le son numérique, et justement échantilloné... Enfin, tout dépned des fréquences que tu as besoin, mais l'érreur systèmatique dans l'émission de fréquence est calculable, et surtout non négligeable si tu tends vers des fréquences soit hautes, soit très basse...
cs_epson1 Messages postés 89 Date d'inscription dimanche 12 novembre 2000 Statut Membre Dernière intervention 29 mars 2013
6 oct. 2005 à 23:22
Salut Grosiflex, tout d'abord ,merci et un grand bravo pour cette source (je t'ai mis que 8 parce que j'ai clické trop vite ...)
C'est vraiment bien codé mais j'ai pas bien compris WinMM et je n'ai rien trouvé sur le net .
Peut être pourrait tu m'aider ?
Comment peut t'on faire pour séparer les canaux et gènèrer une fréquence fixe mais diffèrente ,par exemple ,sur les deux canaux gauche et droite simultanément ? (pas de lecture de fichier ni de streaming ,mais une génération en temps réel).
je cherche à faire un synthétiseur de fréquence pour étalonner un laser et je bloque ici .Toute aide est la bienvenue .
Je te remercie par avance ainsi que tous ceux pouvant m'aider .
Bonne prog à tous et longue vie à VbFrance .
cs_max12 Messages postés 1491 Date d'inscription dimanche 19 novembre 2000 Statut Modérateur Dernière intervention 7 juillet 2014
8 juin 2005 à 01:32
Cette source est tout simplement excellente, 10/10 une révolution sur ce site carrément :)
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
26 déc. 2003 à 08:32
A la base, tout le programme n'est pas de moi, le système de compression si, mais après, le projet ComBox est de Romain LABBE. Par contre, si tu veux utiliser le système de compression, il serait interressant de le developper sous un autre language de manière à optimiser la vitesse le coût CPU qu'il engendre (parce ça, en VB, c'est déplorable...), et de créer une DLL de compression/décompresion de son...
Tiens, je crois d'ailleurs (enfait, je ne me rapelle plus si j'avais implémenté quelque chose à ce sujet, mais je crois pas) qu'il serais utile de traiter les données de son avant l'entrée dans le compresseur, de manière, dans un premier temps, "raboter les raies inutile du spectre" comme disait GroSiFlex, et dans un second temps, distordre légèrement les données de manière à optimiser la compression : Déjà, les silences quasi-complets, on peut les expurger, puis certaines données parfois sont mal venue pour la compression, par exemple, avec un son dont le delta serais celui-ci :
80 -15 +7 +8 -12 +16 -16 + 4
La, cette chaine, pour la compression, C pô terrible, car il faut utiliser une zone dont les données seront codées sur 1+5 = 6bits, alors que si lo'n "rabote" le +16 et le -16 à +15 et -15, le son sera quasi identique (amuse toi bien pour entendre une si petite différence), mais il suffira une zone codée sur 1+4 )= 5bits

donc, dans le permier cas il faut :
[permier octet] + [entête] + [7 points] * [nbre bits / points]
8 + 11 + 7*6 = 61 bits

Et dans le second cas :
8 + 11 + 7*5 = 54 bits

ça fait un gain de 7 bits sur 64, ça fait un gain de 11%...
[PS : J'ai voulu poster ce commentaire déjà aavant-hier, mais le site ne postait pas le msg...]
Vexplore Messages postés 25 Date d'inscription lundi 22 décembre 2003 Statut Membre Dernière intervention 8 octobre 2010
23 déc. 2003 à 21:29
Tout d'abord, MERCI pour tes explications (et avec un delai hyper rapide !!).
Je comprends maintenant mieux la compression.
Par contre j'ai encore un peu de mal avec les appels de .dll (je suis automaticien d'origine et programmeur VB par hobbie).

Alors je vais regarder plus particulièrement ce que je peux faire avec Winmn qui m'interesse pour enregistrer et lire du son.

Ben oui, je ne voudrais pas copier coller ton code (excelent d'ailleurs), mais je vodrais le faire par moi même.

Pour info, je prépare un peu la même chose que toi mais avec un serveur qui accepte plusieurs clients (partie qui est très simple d'ailleurs avec les index de winsock).

J'ai télécharger ton code qui va surement m'aider beaucoup.

MERCI !!!!!

@+
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
23 déc. 2003 à 14:50
Mon dernier commentaire est assez copieux, mais pour ceux qui ont pas tt capté, ça servira de référence...
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
23 déc. 2003 à 14:46
B'1, C 1 vieux kod ke j'aV bricolé mais pas finalisé (j'arrivais pas à trouver 1 tite erreur ki se trimbale par là...)
Pour le système de compression, je me rapelle pas de tout les détails pq ça fait 1 bail que je l'avais fais, ms enfait, pr te donner 1

explication simple, ça donnerai ça :
Tu as un son "brut" en 8 bits, (n'importe quelle frequence...), tu as dc des données constituant ton son sous forme d'octets, comme par

exemple : 80 7F 7E 7A 7E 82 88 90 87 86 85 84 83 82 81 80
Admetons que cette chaine d'octet est un son, tu remarqueras (et j'ai choisi l'exemple exprès) que les valeurs des octets sont proches les

unes des autres, par contre, il peut arriver qd même ds un son d'utiliser tout la plage des valeurs (de 0 à 255), mais, on à jamais un truc

du style 00 FF 00 FF 00 FF (c'est franchement inaudible kom son...), donc, pour compresser en fait, je calcule combien il y a entre 2

octets..

Avec mon exemple : Le premier octet c'est 80 (ça, faut le stocker dans 1 koin...)
Après, on a 7F, c'est 1 en dessous de 80 --> -1
Après, 7E, c'est 1 dessous de 7F --> -1
Après, 7A, c'est 4 dessous de 7E --> -4
Après, 7E, c'est 4 dessus de 7E --> +4
Donc, dans pr reprendre mon exemple, ça donnerai les données que j'appelle Delta (pour différence) :
80 -1 -4 +4 +3 +6 +8 -9 -1 -1 -1 -1 -1 -1 -1
Donc, avec ces données, on reconstitue aisément le son, il suffit de transformer ça ds le sens inverse koi...
Ces données, C bô, ms quel interêt ??? Ben, avec un son, les données, comme je l'ai déjà écrit tout à l'heure, sont proches les unes des

autres, ce qui fait que les nombres DELTA sont généralement petits (/! ms pa tt le tps).
Bon, compresser, c'est réduire la place utilisée par le fichier, c'est donc réduire le nombre de bits utilisé pour stocker les données...
Donc, là, au lieu de coder chaque "points" du son (qui correspondent à 1 octet pr du son numérisé en 8 bits) avec 1 octet, on va faire

moins...
Oui, car pour coder des valeurs comme ça, ya pas besoin de tant de bits...
avec 8 bits, on peut coder de 0 à 255 (2^8-1)
avec 7 bits, on peut coder de 0 à 127 (2^7-1)
bon, moi, mes données, déjà, elle ont un signe + ou -, donc avant de coder le nombre en lui même, faut coder le signe, pour ce faire, on

utilisera 1 bit, s'il est 0 ça sera un signe, s'il est à 1, ça sera l'autre (je me rappelle plus ce que j'avais utilisé... 0 -> + et 1

--> - il me semble, ms c'est peut-être le contraire...)
Donc du coup, pour stocker des données allant de -255 à +255, j'utilise 1 bit + 8 bits (bon, ça c'est 1 système un peu de bricoleur, les

nombres signés ne sont pas d'habitude stockés comme ça, mais, je l'ignorais qd j'ai créé mon prog... Mais, en terme de place, ça revient au

même, donc...)
Bon, donc, du coup, là, avant on stockait sur 8 bits tout le temps, mais moi, il va m'en falloir 9, mais AU MAXIMUM, car si les nombres à

stocker sont compris entre :
-127 et +127 --> 1 + 7 = 8 bits
-63 et +63 --> 1 + 6 = 7 bits
-31 et +31 --> 1 + 5 = 6 bits
-15 et +15 --> 1 + 4 = 5 bits
-7 et +7 --> 1 + 3 = 4 bits
-3 et +3 --> 1 + 2 = 3 bits
-1 et +1 --> 1 + 1 = 2 bits
(Et si on a une chaine de 0, on va se débrouiller pour n'utiliser aucun bits supplémentaires)
Donc, en fait, on va utiliser pour coder, le nombre de bits qui permette de coder les nombres auxquels on s'interresse le plus habile, et

surtout le plus économiseur de place.
Mais, si j'utilise (ac mon exemple) : 1 octet classique pr la 1ere valeur, puis 2 bits pour le 1er delta, puis 4 pour les deux suivants, puis

3,puis 4, puis 5 et 5 et 2 jsuqu'a la fin de l'exemple, là, on a une compression qui est quasi-idéale... Je vais convertir ça en binaire pour

la compréhension...
L'exemple original converti en binaire :

HEX : 80 | 7F | 7E | 7A | 7E |
BIN : 10000000|01111111|01111110|01111010|01111110|
Bon, je vais pas tous me les taper, ça sert à rien à partir du moement ou c'est compréhensible... Donc, ici, dans l'exemple complet du haut,

j'avais 16 octets, donc 16*8 = 128 bits...

Bon, alors, avec la compression idéaliste, on aurait :

DELTA : | 80 |-1 | -4 | +4 | +3 |
BINAIRE : |10000000|1 1|1 100|0 100|0 11|

Si je comprae les 2chaines en mettant tout bout-à-bout, comme ça serais dans 1 fichier en réalité :
Non Compressé :
1000000001111111011111100111101001111110
Compressé :
100000001111000100011

Génial hein ? Et ben non, pas génial du tout... Pourquoi ? Parce, on gagne bcp de place, mais ça sert à rien, pq, la, on a compressé le son,

très bien, mais, on pourras jamais le décompresser car la chaine que j'ai obtenue ne continent aucune information indicant sur combien de

bits on a codé, bon, pr le premier "Point", ça va, on sait qu'il est directement codé sur 8 bits "classiques", mais apprès, le "point"

d'après, c'est quoi ? 11 --> -1 ou 111 --> -3 ou 1111 --> -7 ou 11110 --> -14 ???????? Impossible de savoir...
Donc, il faut rajouter à cette chaine de bits l'information suviante : sur combien de bits est stocké le "point" suivant...

Bon, là, je vais refaire 1 shéma complet, mais, pour coder (dans ce que je vais appeler l'entête) le nombre de bits allant de de 9 jusqu'a 2,

donc la, pour planifier la chose, je donne petit tableau :
Possibilités de codage :
9 bits, 8 bits, 7 bits, 6 bits, 5 bits, 4 bits, 3 bits, 2 bits --> 8 possibilités

Pour coder ce nombre de bits en binaire, on va procéder comme suit (sur 3 bits) :
000 -> 2 bits
001 -> 3 bits
010 -> 4 bits
011 -> 5 bits
100 -> 6 bits
101 -> 7 bits
110 -> 8 bits
111 -> 9 bits

Bon, donc, avec ce système, avant chaque flot de bits représentant 1 "point" (sauf le 1er, pq lui, il sera tjours sur 8 bits), sera précédé

de cette entête de 3 bits indiquant combien y a-t-il de bits de données :
Si je reprend le ti tableau avec la compression idéaliste de tout à l'heure,
DELTA : | 80 |-1 | -4 | +4 | +3 |
BINAIRE : |10000000|1 1|1 100|0 100|0 11|
Je reprend les bits, et j'intercale les entêtes...

10000000|000-11|010-1100|010-0100|001-011|
[j'ai mis des symboles pour bien séparer, la forme est donc : 1erPointCodéSur8Bits|Entête-Données|Entête-Données|Entête-Données...]

Donc, en rassemblant ces bits, on a :

100000000001101011000100100001011




Si on compare avec la chaine non compressée, c'est 1 peu mieux sur mon exemple :


100000000001101011000100100001011 'Compressée
1000000001111111011111100111101001111110 ' Non compressée

Mais, c'est pas terrible quand même, hein ?
Qu'est-ce qui nous bouffe de la place maintenant ? Ces entêtes...
Comment faire ? [Moi aussi je me suis 1 jr posé la question...]
Ben, avec un peu de déduction, je me suis dit, fo pas qu'il y ait tant d'entêtes... Jusque là, c'est assez logique... Et je me suis dit

aussi, à la limite, il vaut mieux une grosse entête de 16 bits pour mettons 6 "points" que 1 entête de 3 bits pour chaque point : et oui, si

j'arrive à faire une entête de 16 bits pour 6 points, ça fait 16 bits en entête, alors que si j'ai 6* 3 bits d'entête, ça en fait 18...
Alors, comment faire ? Ben, en me creusant la cervelle, j'ai pencé (et à bon escient je crois) qu'il fallait faire 1 entête pour x bits, et

il faudrais donc inscrire dans cette entête x mais aussi le nbre de bits pour chaque points, et c'est sur ce dernier point que j'avais des

problèmes : si je remet comme auparavant 3 bits pour chaque point, j'ai pas résolu mon problème car mon entête globale sera forcément plus

longue que les entêtes par points comme j'avais fait au dessus, donc, je vais avoir un taux de compression encore plus bas, et peut être même

que le fichier compressé sera plus gros que l'original ! Donc, je me suis dit, il faudrait que les x points que l'on va coder soient codés

sur un même nombre de bits, comme ça, il n'y aurait besoin que d'une seule suite de 3 bits pour indiquer le nombre de bits utilisés pour

coder les données...
Et la est la clef du système :
Il faut regrouper INTELLIGEAMENT (j'insiste...) les "points" par packet que l'on codera sur un MEME nomrbre de bits, et on créra une entête

de la forme : 3 bits pour l'info : nombre de bits codant + des bits codant le nombre de "points" du packet.
1 enête comme ça + 1 packet de données = 1 ZONE (c'est comme ça que je l'ai dénommé...)
Il reste deux choses à éclaircir :
- dans la phrase de description j'ai mis "+ DES bits codant", et oui ce DES, c'est zoli, ms c'est drôlement embétant, il faut à tout prix

qu'on sache combien il va y en avoir, autrement, on va pas pouvoir décompresser, pq on va pas savoir combien, à ce stade, de bits faudra lire

pour connaître ce nombre [désolé si je m'enfonce 1 peu avec des phrases contenant 10 fois le mot bit...]... Bon, là, faut arrêter de ce

prendre la tête, ce nombre, il suffit de le fixer ! On dit, que dorénavent, on utilisera 8 bits pour coder ce nombre, et, ça posera plus de

problèmes ! Si un : sur 8 bits, on peut coder, classiquement de 0 à 255, bon, la, 0, ça n'arrivera jamais qu'on ait un zone de 0 points, donc

la, déjà, ça exclu 1 cas... Tien, au fait, est-ce possible 1 ? Je ne m'étais jusqu'a présent jamais posé la question... Oui, si, c'est

possible : regardez : imaginez un son très plat et pile au milieu, ya en gros pic, juste sur 1 point (enfin, avec les deltas, c'est un peu

artificiel ms bon, c'est pour être sur que mon système compresse absolument tout les sons 8 bits...), on va avoir par exemple une zone codant

240 points sur relativement peu de bits, par exemple 2, donc, ça, ça fait combien de place pr stocker ça ?
ENTETE + DONNEES
3 + 8 + 240 * 2 11 + 480 491 bits.
Bon, on imagine qu'on a 2 fois cette même chaine, et pile au mileir, on a un pic, avec un delta = +128, il va falloir le coder sur 9 bits

lui...

Alors, si je fais qu'une zone globale (je rappelle on cosidère qu'on a un son plat compressé sur 491 bits, puis le pic, puis un autre son

plat codé aussi sur 491 bits), on va être obligé de coder TOUTE la zone sur 9 bits :
ENTETE+ DONNEES
3 + 8 + 9 * (240 + 1 + 240) 11 + 9*481 4340 bits Oula...
Effectiment, c'est très nul ça..
Par contre, si on crée une zone pour ce point, on va avoir :

ENTETE+ DONNEES+ ENTETE+ DONNEES+ ENTETE+ DONNEES
3 + 8 + 240 *2 + 3 + 8 + 1 * 9 + 3 + 8 + 240 * 2 33 + 960 + 9 1002 bits, c'est mieux ! largement...

Sachant que l'original d'un tel son aurait fait : (240 + 1 + 240) * 8 481 * 8 3848 bits

C'est-ti pô génial ? lol !
Bon, donc, le second des deux problèmes que j'évoquais plus haut, c'est comment regrouper INTELLIGEAMENT.. héhé...
Ben en fait, là, la meilleure technique ça serais de tester... Mais, bon, tester, C long, vaut mieux à ce moment là faire un petite étude

statistique comme j'ai fais a dessus, en évaluant le nombre de bits utilisés suivant tel ou tel cas...
C'est donc la DETERMINATION DES ZONES.
La je prend les deux premiers points, je calcule statistiquement combien de bits il me faudrait pour les coder séparément, puis après, je

fais la même étude en les codant ensemble, et je retiens la meilleure méthode.
Donc, si il vaut mieux les coder séparément, je crée 2 zones, une pour chaqun, et si il vaut mieux les coder ensemble, je ne cré qu'une zone.
Ensuite, je vais faire la même étude statistique que précédament, mais cette fois-çi avec la dernier zone que j'ai créé et le point à coder,

et la, pareil, 2 cas, et je cré des zones en fonction de ça... C'est une méthode qui marche fort bien, c'est la meilleure, car il peut

s'avérer qu'on puisse faire mieux que ce prédira mon système, par exemple, sur 4 points (A B C et D) :
Test de A avec B --> Il vaut mieux les mettre ensemble, créantion de la zone AB
Test de AB et C --> Il vaut mieux les séparer, on garde la zone AB, et on crée la zone C.
Test de C avec D --> on les assemble en 1 zone CD

Donc, au final, on aurait là 2 zones : AB et CD qui vont coûter un certain nombre de bits, mais peut être qu'on aurait pu gagner ayant A tout

seuln puis BC puis D.
Bon, la sur des points uniques comme ça, c'est pas réellement possible, mais sur des chaines des points, ça peut arriver...

D'aillerus, j'y repense, dans mon code, avant cet algorythme, je procédais à 1 autre, qui avait pour but de créer déjà des zone si on avait

des points qui nécessitaient un même nombre de points...Ben voilà, gro pavé explicant le fonctionnement de système !
Je suis en train de penser : Ne serait-il pas plus intelligent et plus court de créer une seule entête au début du fichier incant les numéros

des points codés sur 2 bits, 3 bits, 4 bits, 5 bits... ectect...
Aussi, je crois que j'avais bricolé un ti système qui permettais d'avoir une entête indiquant un nombre de zones, mais toutes codées sur 0

bits, dans ce cas, il n'y a pas de bits de données à la suite, et les x points indiqués on un DELTA de 0, donc sont tous égaux au point

précédent juste la zone...

Bon, b'1 maintenant, ya plus qu'a faire chemin inverse pour la décompression ! [c'est + plus, ya qu'a lire les entêtes, puis les données kom

il faut, et C bon...]

Aussi, je vous le dit : en VB, ça, c'était la pire idée que j'ai pu avoir ce jour là... Faudrais refaire ça en C++ au moins...
Si yen a qui après ça ont encore des questions, ou des idées ou autre, je suis toujours là !
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
23 déc. 2003 à 14:43
Grosiflex : c'est lourd, mais parce que c'est mal codé, et en plus en VB : Donc, la source, à la limite, faut même pas la regarder, il faut regarder le principe, en suite, pour l'analyse du spectre, pour écréter les données inutiles, il suffirait de le faire avant, et j'aimerai bien explorer 1 peu 7 iD, tu peux m'en dire plus long à ce sujet ?
Vexplore : La source est cencée être dans le ZIP, je vérifie tout de même...
Vexplore Messages postés 25 Date d'inscription lundi 22 décembre 2003 Statut Membre Dernière intervention 8 octobre 2010
22 déc. 2003 à 14:14
Merci de mettre la source à disposition.
Les commentaires ont l'air exélent, je vais donc regarder et essayer de comprendre.
Par contre j'ai pas tout compris sur la compression pour le moment.

@+
grosiflex Messages postés 19 Date d'inscription jeudi 4 octobre 2001 Statut Membre Dernière intervention 21 octobre 2004
10 mars 2003 à 12:57
ourch,
si ca marche c'est tres bien, mais je trouve ca archi lourd deja, alors que tu ne travail pas sur le spectre, alors imagine si tu commence a vouloir raboter les raies inutile du spectre, aille !
tu arrive a quelle rendement avec ce systme ?
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
28 févr. 2003 à 21:09
Voici mon code de compression un chouïa optimisé, pas encore top, mais je pense avoir fait déjà pas mal !
Option Explicit

Dim Boucle As Long

Private Type BitsZoneType
LenghtZone As Long
ZoneType As Integer
EmptyCase As Boolean
End Type

Public Function CompressStringSound(inString As String,OutString As string)
' On alloue à chaque octet, une case du tableau d'octets DataArray
' On fait la différence de valeur relative entre chaque octet
' On calcule combien de bits il faudrait pour la stocker

ReDim DataArray(Len(inString))
ReDim RelativeDataArray(Len(inString))
ReDim RelativeDataBitsNeededArray(Len(inString))
Dim EcartMaxPos As Byte, EcartMaxNeg As Byte
For Boucle = 1 To Len(inString)
DataArray(Boucle) = Asc(Mid(inString, Boucle, 1))
RelativeDataArray(Boucle) = CInt(DataArray(Boucle)) - CInt(DataArray(Boucle - 1))
Select Case Abs(RelativeDataArray(Boucle))
Case 0
RelativeDataBitsNeededArray(Boucle) = 1
Case Is <= 2 ^ 1 - 1
RelativeDataBitsNeededArray(Boucle) = 2
Case Is <= 2 ^ 2 - 1
RelativeDataBitsNeededArray(Boucle) = 3
Case Is <= 2 ^ 3 - 1
RelativeDataBitsNeededArray(Boucle) = 4
Case Is <= 2 ^ 4 - 1
RelativeDataBitsNeededArray(Boucle) = 5
Case Is <= 2 ^ 5 - 1
RelativeDataBitsNeededArray(Boucle) = 6
Case Is <= 2 ^ 6 - 1
RelativeDataBitsNeededArray(Boucle) = 7
Case Is <= 2 ^ 7 - 1
RelativeDataBitsNeededArray(Boucle) = 8
Case Is <= 2 ^ 8 - 1
RelativeDataBitsNeededArray(Boucle) = 9
End Select
Next

' On regroupe par zone(de 2^7 caractères max) les caractères ayant besoin d'un même nombre de bits pour être stockés
Dim BitsZone() As BitsZoneType
Dim CurrentZone As Integer, CurrentLengthZone As Long, CurrentNzone As Long
Dim ItIsTheFirstZone As Boolean
ItIsTheFirstZone = True
CurrentZone = -1
For Boucle = 1 To Len(inString)
If CurrentZone <> RelativeDataBitsNeededArray(Boucle) Or CurrentLengthZone > 2 ^ 7 Then
ReDim Preserve BitsZone(CurrentNzone)
If ItIsTheFirstZone = False Then
BitsZone(CurrentNzone).ZoneType = CurrentZone
BitsZone(CurrentNzone).LenghtZone = CurrentLengthZone + 1
CurrentNzone = CurrentNzone + 1
Else
ItIsTheFirstZone = False
End If
CurrentZone = RelativeDataBitsNeededArray(Boucle)
CurrentLengthZone = 0
Else
CurrentLengthZone = CurrentLengthZone + 1
End If
Next
Dim NumberOfZones As Long
NumberOfZones = CurrentNzone
'Form1.List1.AddItem "Non regroupé :"
'For Boucle = 0 To NumberOfZones - 1
' Form1.List1.AddItem "Zone " & Boucle & " : Type " & BitsZone(Boucle).ZoneType & " sur " & BitsZone(Boucle).LenghtZone & "Caractère(s)"
'Next

'On rentabilise (en taille) ces zones de manière à ce que la zone + l'entête de zone ne soit pas plus grande qu'une zone plus globale avec sn entête (éviter les zones de trop courtes taille qui demandent plus de bits pour l'entête que pour les données elles-même)
Dim bitszone_ZoneTypeMax As Integer, NextUnusedZone As Long
CurrentNzone = 0
Do
' Recherche de la prochaine zone non vide (mise en variable dans NextUnusedZone), si aucune ExitDo
Dim SearchBoucle As Long
SearchBoucle = CurrentNzone + 1
NextUnusedZone = -1
Do
If BitsZone(SearchBoucle).EmptyCase = False Then
NextUnusedZone = SearchBoucle
Exit Do
End If
SearchBoucle = SearchBoucle + 1
Loop While SearchBoucle < NumberOfZones
If NextUnusedZone = -1 Then Exit Do

' Recherche du nombre de bits necéssaire au codage dans la zone courante et la suivante, on met en variable la plus grande
If BitsZone(CurrentNzone).ZoneType > BitsZone(NextUnusedZone).ZoneType Then bitszone_ZoneTypeMax BitsZone(CurrentNzone).ZoneType Else bitszone_ZoneTypeMax BitsZone(NextUnusedZone).ZoneType
' Si l'on réalise un économie à regrouper la zone courante et la suivante plutot que de les juxtaposer, sans tout de même, dépasser les 2^11 caractères maximums par zone
If BitsZone(CurrentNzone).ZoneType * BitsZone(CurrentNzone).LenghtZone + 5 + 7 + BitsZone(NextUnusedZone).ZoneType * BitsZone(NextUnusedZone).LenghtZone + 5 + 7 > bitszone_ZoneTypeMax * (BitsZone(CurrentNzone).LenghtZone + BitsZone(NextUnusedZone).LenghtZone) + 5 + 7 And BitsZone(CurrentNzone).LenghtZone + BitsZone(NextUnusedZone).LenghtZone <= 2 ^ 7 Then
' On le fait !
BitsZone(CurrentNzone).ZoneType = bitszone_ZoneTypeMax
BitsZone(CurrentNzone).LenghtZone = BitsZone(CurrentNzone).LenghtZone + BitsZone(NextUnusedZone).LenghtZone
BitsZone(NextUnusedZone).ZoneType = -1
BitsZone(NextUnusedZone).EmptyCase = True
CurrentNzone = 0
' sinon, on passe son chemin et on teste avec les suivantes
Else: CurrentNzone = NextUnusedZone
End If
Loop
Dim LenTotal As Long

Dim BitsZoneOptimized() As BitsZoneType, CurrentLine As Long
ReDim BitsZoneOptimized(NumberOfZones)
For Boucle = 0 To NumberOfZones - 1
If BitsZone(Boucle).EmptyCase = False Then
BitsZoneOptimized(CurrentLine).LenghtZone = BitsZone(Boucle).LenghtZone
BitsZoneOptimized(CurrentLine).ZoneType = BitsZone(Boucle).ZoneType
Form1.List1.AddItem "Zone " & CurrentLine & " : Type " & BitsZoneOptimized(CurrentLine).ZoneType & " sur " & BitsZoneOptimized(CurrentLine).LenghtZone & "Caractère(s)"
LenTotal = LenTotal + 5 + 7 + BitsZoneOptimized(CurrentLine).ZoneType * BitsZoneOptimized(CurrentLine).LenghtZone
CurrentLine = CurrentLine + 1
End If
Next

NumberOfZones = CurrentLine
ReDim Preserve BitsZoneOptimized(NumberOfZones)

Form1.Label1.Caption = LenTotal / 8
Form1.Label2.Caption = NumberOfZones
End Function
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
28 févr. 2003 à 13:26
J'ai changé le nombre de bits pour l'entète : je suis passé de 16 à 12, et alors, là,

j'ai tout gagné ! La compression est un peu meilleure quand on a beaucoup de zone

(quand il y a des paroles), mais vraiment meilleure quand le son se fait plus discret

!
D'ailleurs je crois que je vais mettre une taille d'entête variable calculée avant !
voici le code provisoire de calcul des zones que je vais re-améliorer !
Il faut sur une form 2 labels, une list !

Option Explicit

Private Type BitsZoneType
LenghtZone As Long
ZoneType As Integer
End Type

Dim Boucle As Long

Private Sub Form_Load()
Me.Show

Dim NItérations(255) As Long, DataArray() As Byte, RelativeDataArray() As Single
Dim RelativeDataArrayBitsNeeded() As Integer

' Extraction de la viariable d'entrée InString depuis un fichier (provisoire)
Dim inString As String
Open "D: est.son" For Binary As #1
inString = Space(LOF(1))
Get #1, , inString
Close
' Découpage d'un morceau du fichier :
inString = Mid(inString, 1, 8192)

' On alloue à chaque octet, une case du tableau d'octets DataArray
' On fait la différence de valeur relative entre chaque octet
' On calcule combien de bits il faudrait pour la stocker

ReDim DataArray(Len(inString))
ReDim RelativeDataArray(Len(inString))
ReDim RelativeDataArrayBitsNeeded(Len(inString))
Dim EcartMaxPos As Byte, EcartMaxNeg As Byte
For Boucle = 1 To Len(inString)
DataArray(Boucle) = Asc(Mid(inString, Boucle, 1))
RelativeDataArray(Boucle) = CInt(DataArray(Boucle)) -

CInt(DataArray(Boucle - 1))
Select Case Abs(RelativeDataArray(Boucle))
Case 0
RelativeDataArrayBitsNeeded(Boucle) = 1
Case Is <= 2 ^ 1 - 1
RelativeDataArrayBitsNeeded(Boucle) = 2
Case Is <= 2 ^ 2 - 1
RelativeDataArrayBitsNeeded(Boucle) = 3
Case Is <= 2 ^ 3 - 1
RelativeDataArrayBitsNeeded(Boucle) = 4
Case Is <= 2 ^ 4 - 1
RelativeDataArrayBitsNeeded(Boucle) = 5
Case Is <= 2 ^ 5 - 1
RelativeDataArrayBitsNeeded(Boucle) = 6
Case Is <= 2 ^ 6 - 1
RelativeDataArrayBitsNeeded(Boucle) = 7
Case Is <= 2 ^ 7 - 1
RelativeDataArrayBitsNeeded(Boucle) = 8
Case Is <= 2 ^ 8 - 1
RelativeDataArrayBitsNeeded(Boucle) = 9
End Select
Next

' On regroupe par zone(de 2^7 caractères max) les caractères ayant besoin

d'un même nombre de bits pour être stockés
Dim BitsZone() As BitsZoneType
Dim CurrentZone As Integer, CurrentLengthZone As Long, CurrentNzone As Long
Dim ItIsTheFirstZone As Boolean
ItIsTheFirstZone = True
CurrentZone = -1
For Boucle = 1 To Len(inString)
If CurrentZone <> RelativeDataArrayBitsNeeded(Boucle) Or

CurrentLengthZone > 2 ^ 7 Then
ReDim Preserve BitsZone(CurrentNzone)
If ItIsTheFirstZone = False Then
BitsZone(CurrentNzone).ZoneType = CurrentZone
BitsZone(CurrentNzone).LenghtZone = CurrentLengthZone + 1
CurrentNzone = CurrentNzone + 1
Else
ItIsTheFirstZone = False
End If
CurrentZone = RelativeDataArrayBitsNeeded(Boucle)
CurrentLengthZone = 0
Else
CurrentLengthZone = CurrentLengthZone + 1
End If
Next
Dim NumberOfZones As Long
NumberOfZones = CurrentNzone
List1.AddItem "Non regroupé :"
For Boucle = 0 To NumberOfZones - 1
List1.AddItem "Zone " & Boucle & " : Type " & BitsZone(Boucle).ZoneType &

" sur " & BitsZone(Boucle).LenghtZone & "Caractère(s)"
Next

'On rentabilise (en taille) ces zones de manière à ce que la zone + l'entête

de zone ne soit pas plus grande qu'une zone plus globale avec sn entête (éviter les

zones de trop courtes taille qui demandent plus de bits pour l'entête que pour les

données elles-même)
Dim bitszone_ZoneTypeMax As Integer
CurrentNzone = 0
Do While CurrentNzone < NumberOfZones
' Recherche du nombre de bits necéssaire au codage dans la zone courante

et la suivante, on met en variable la plus grande
If BitsZone(CurrentNzone).ZoneType > BitsZone(CurrentNzone + 1).ZoneType

Then bitszone_ZoneTypeMax BitsZone(CurrentNzone).ZoneType Else bitszone_ZoneTypeMax
BitsZone(CurrentNzone + 1).ZoneType
' Si l'on réalise un économie à regrouper la zone courante et la suivante

plutot que de les juxtaposer, sans tout de même, dépasser les 2^11 caractères

maximums par zone
If BitsZone(CurrentNzone).ZoneType * BitsZone(CurrentNzone).LenghtZone +

5 + 7 + BitsZone(CurrentNzone + 1).ZoneType * BitsZone(CurrentNzone + 1).LenghtZone +

5 + 7 > bitszone_ZoneTypeMax * (BitsZone(CurrentNzone).LenghtZone +

BitsZone(CurrentNzone + 1).LenghtZone) + 5 + 7 And BitsZone(CurrentNzone).LenghtZone

+ BitsZone(CurrentNzone + 1).LenghtZone <= 2 ^ 7 Then
' On le fait !
BitsZone(CurrentNzone).ZoneType = bitszone_ZoneTypeMax
BitsZone(CurrentNzone).LenghtZone = BitsZone(CurrentNzone).LenghtZone +

BitsZone(CurrentNzone + 1).LenghtZone
BitsZone(CurrentNzone + 1).ZoneType = -1
BitsZone(CurrentNzone + 1).LenghtZone = 0
' On décale tout les membres du tableau d'un cran vers le haut en

écrasant l'élément qui est devenu un doublon, et on supprime sa dernière ligne
For Boucle = CurrentNzone + 1 To NumberOfZones - 2
BitsZone(Boucle).LenghtZone = BitsZone(Boucle + 1).LenghtZone
BitsZone(Boucle).ZoneType = BitsZone(Boucle + 1).ZoneType
Next
NumberOfZones = NumberOfZones - 1
ReDim Preserve BitsZone(NumberOfZones)
CurrentNzone = 0
' sinon, on passe son chemin et on teste avec les suivantes
Else: CurrentNzone = CurrentNzone + 1
End If
Loop
Dim LenTotal As Long
List1.AddItem "Regroupé :"

For Boucle = 0 To NumberOfZones - 1
List1.AddItem "Zone " & Boucle & " : Type " & BitsZone(Boucle).ZoneType &

" sur " & BitsZone(Boucle).LenghtZone & "Caractère(s)"
LenTotal = LenTotal + 5 + 7 + BitsZone(Boucle).ZoneType *

BitsZone(Boucle).LenghtZone
Next
Label1.Caption = LenTotal / 8
Label2.Caption = NumberOfZones

End Sub
Ludolpif Messages postés 138 Date d'inscription samedi 11 mai 2002 Statut Membre Dernière intervention 17 mai 2007
28 févr. 2003 à 10:51
Vraiment bien comme système de compression ! Figure toi(grosiflex) que quand j'ai

commencencé à chercher j'ai fait EXACTEMENT la même démarche que toi. J'ai enregistré

du son, je me suis dit, on pourrait se taper une delta, j'ai pensé au truc de la

moyenne, mais bon je m'suis, la delta marchera certainement mieux (d'ailleurs, j'ai

presqu'envie de coder la 2 voir les résultats, et même mettre une petite balise au

début pour que le decompresseur utilise un système ou l'autre).
Mais, moi j'ai poussé le bouchon plus loin que toi : j'arrive à la même compression

sans perdre la moindre information !
Je me suis dit ya plein de différences proches de 0, Ce serai quand même mieux de

coder ça sur des enchainemeent binaires plus petits que l'octet. Alors, j'ai fait un

code général : J'ai pris chaqune de mes valeurs diférentielles, et j'ai construit un

tableau avec le nombre de bits nécessaires pour l'encoder (avec le même problème de

signe, donc j'ai moi aussi rajouté un bit). Et je me suis dit que je pourrai faire un

système de Zones : Ben ouais, une zone ce serait un entête de 2 octets ou les 5

premiers bits servent à dire "dans cette zone, les caractères sont codés avec x bits

chacuns" (x alant de 1 à 9), et les 11 autres servent à dire "dans cette zone x

caratères sont codés", mais je sait qu'11 bits ça fait trop pour rien, mais c'était

pour completer mes 2 octets, mais ça je le modifirai un peu plus tard, quand j'aurai

remis au propre ma scr.
Bon, en partant de la, j'ai fait un zone par caractère, donc je me suis retrouvé avec

16 bits d'entète x bits de codé : j'ai multiplié taille du fichier pat 5 ou 10 !
BOn, et c'est la suite ou ça devient interressant et un peu hard : C'est le

regroupement de zones, 1erement, de même nature (c-à-d, de même nombre de bits pour

l'encodage), bon ça pas compliqué : si MonTableauZone(ZoneEncours).NBitsEncodage =

MonTableauZone(ZoneEncours+1).NBitsEncodagepuis then...., la C simple, mais c'est

après, parceque ça ne suffsait pas : un exemple simple à comprendre :
Comme données, j'ai ça :
123
124
122
122
124
123
Bon alors, le différentiel, ça donne ça :
+123
+1
-2
+0
+2
-1
Et le système de création de zone, me donne pour les données, le nombre de bits

minimal qu'il faut pour les stocker :
+123 --> 7+1bits (7 pour le nombre 123, et 1 de + pour le signe)
+1 2 bits
-2 3 bits
+0 1 bit
+2 3 bits
-1 2 bits
Mon sytème pour regrouper les zone, là, eh ben je l'ai dans le c.. ! Pas 2 zones

identiques. En plus, la la taille que ça va me prendre :
8+2+3+1+3+2 19 bits pour les données pures + 6 * 16 96 bits pour les entêtes
total : 115 bits, alors qu'avant la compression yavait 6 * 8 = 48 bits
Ratio : 320 %
Bof, ya mieux comme compresseur de données, celui là, il me multiplie la taille par

3...
Donc, vous l'aurez compris, il faut regrouper des zones, même si elle n'ont pas le

même nombre de bits...
Alors, pour,il "suffit" de prendre 2 zones, de prendre la plus grande valeur du

nombre de bits minimal necéssaire pour encoder, et coder toutes les données (zone 1

et 2) avec ce même nombre de bits, 'core un exemple :
+123 7b
+1 2b
-2 3b
Si on s'interresse aux zones 2 et 3, si on les laisse tels quel, les 2 vont prendre

1(nombre de caractère codés dans la zone) * 2(data zone 2) + 2*8 (entete Zone2)

+1(nombre de caractère codés dans la zone) * 3(data zone 3) + 2*8 (entete Zone 3) =

37 bits
Mais si je les regroupe :
on aura une zone avec :
2(nombre de caractères codés dans la zone groupée) * 3(data zone groupée) + 2*8

(entete Zone groupée) = 24 bits !
Et voilà, le truc est la, regrouper des zones !
C'est merveilleux, non ????
Eh ben non, justement non, parce qu'il peut y avoir des cas merdiques :
avec le même exemple, si je regroupe la zone que je veint de créer avec la 1ere, é

ben, la taille va augmenter en flèche. Donc, il ne faut le faire si c'est rentable !
Moyen le plus simple de savoir si c'est retable, tester !
On calcule la place qu'il faudrait si la zone qu'on est en train de tester et la zone

qui suit si elle étaient juxtaposées, et si elle étaient groupées, et la si C

rentable en taille on groupe, autrement on teste les zones suivantes !
Et maintenant c'est merveilleux, on gagne de la place à tout les coups, et tout et

tout....
Mais ya enkor un méga problème :
Vous vous rappellez le tableau que j'ai fait qui contient TOUTES les zones, au

départ, ya autant de zones que d'octets à placer, donc si pour une raison quelconque

mon PC s'est mis à rammer et que le buffer à compresser s'est

remplit,remplit,remplit,remplit... jusqu'a par exemple 15 secondes de son --> + de

200Ko en 8Ko/s, 8bits/frames.
Et ben c'est la merde, mon tableau de + de 200000 lignes, si je regroupe la première

zone, et la 2nde dans la première, ya un trou à la ligne 2, donc on décale les 199998

lignes qu'ill y en dessous de la ligne 2 d'un cran vers le haut, et rien que ça,

déjà... mais le pire c'est que regroupper des zones, mon prog, il le fait sir plein

de zone : exemple il teste la 1 et la 2 : pas rentable, on passe, il teste la 2 et la

3 c'est rentable, il groupe, mais il faut tout recommencer, parce que peut--être que

maintenant, la 1 et la 2 c'est rentable, admetons que ça l'est, on en 3 zones, on

fait 2 regroupements, et c'est souvent comme ça, donc des regroupements, mon prog, il

en fait quasiment tout le temps, au moins un nombre supérieur à la moitiée du nombre

de zone, autrement dit, ici , il en fait au moins 100000, total, il faut déplacer un

nombre incroyable de lignes a chaque regroupement, et ça 100000 fois rien que pour

compresser 200 Ko, soit 15 secondes de son !
Moi, mon PC, il y a mit 2 heures, et pourtant, c'est un bon 1533 MHz !
Bon, ben je sait comment résoudre la problème, il faut créer les zones soit dans un

autre tableau, soit directement regroupées... Mais j'ai pas eu le temps de le faire !
Aussi, c'est beau d'avoir fait lees zones, mai après, faut les écrire! J'ai pas

encore fait le code pour ça, mais lui aussi risque de pomper pas mal d'énergie...
Et c'est la les limites de code VB mal optimisé. T'es obligé d'optimiser à fond, mais

t'es pas sur d'avoir un résultat...
Aussi, fodra que je voit d'intégrer un run-lenght dans le code.
Grosiflex, tu peut expliquer un peu ce qu'est un FFT, parce que ça a l'air

interressant à dévellopper, mais j'ai pas la moindre idée de comment ça marche !
Pfiouuu, fini, le comment !
Mais il faut aussi faire plutôt que de parler et toujours parler comme Ferarien

(Rafarin) !
Sur ce, bonne prog a tous !
grosiflex Messages postés 19 Date d'inscription jeudi 4 octobre 2001 Statut Membre Dernière intervention 21 octobre 2004
27 févr. 2003 à 19:48
j'ai recu pas mal de mail aussi sur la compression.
deposez vos explications ici, ce serait mieux ;)
voila donc mon systeme de codage qui compress pas mal, mais avec un fft par dessus ca serrait le tope
il y'a quelques distortion assez peut perceptible, cette compression est destructive...

points clef: (je me basse sur du 8khz 8 bit pour + de comprehenssion)
------------

deja si vous mattez les valeur d'un signel audio. (mettez la sortie de winmm en 8bit, et ecrire les données ligne par ligne dans un fichier et parlez dans votre micro)
vous verez tres vite que les valeurs sont tres proches les une des autres, j'ai donc opté pour un codage delta...
c'est a dire que j'envois la diference entre chaque echantillons et pas l'echantillon lui meme
le 1er echantillon est envoyé, puis la 2nd valeur est la difference entre les 2 echantillons..
vous me suivez ?
sur un buffer entier on a donc une premeire valeur puis des valeur assez petites (proche de zero)
maintenant imaginé qu'on fait la moyenne de TOUTES ces valeurs et que l'on balance:
d'abors la valeur de la moyenne, puis ensuite la difference entre les valeur (elle meme differentielle).
on a donc des valeur encore + proche de zero que tous...
un buffer plein de valeur proche de zero et un octet en + pour la moyenne)
ou est la compression me direz vous ?
attendez...

imaginez maintenant, que les donnees envoyé ne soit pas de la meme taille, c'est a dire que le code pour representez un octet ne soit pas 8 bit o_O

on sait aussi que:
-nos valeur sont proche de zero !

donc on a besoin de presision dans les petite valeurs et moins dans les grandes valeurs...

ainsi on pose:

1 =0
01 =1
001 =2
0001 =4
00001 =8
000001 =16
0000001 =32

voyez vous l'intert d'un tel codage ?
la presision est dans les petites valeurs et le nombre de bits pour celle si est petits,
comme on en a beaucoup, c'est plutot cool...
et puisqu'il est de longeur variable (c'est du binaire ici), pour le decodage il faut une 'balise', icic le bit a 1
mais au fait, la difference peut etre + ou - ?
oui, obligé de rajouter un bit alors...

1 =0
010 =+1
0010 =+2
00010 =+4
000010 =+8
0000010 =+16
00000010 =+32

1 =0
011 =-1
0011 =-2
00011 =-4
000011 =-8
0000011 =-16
00000011 =-32

voila, rien ne nous empeche de continuer le code, ou de modifier les valeurs de precisions, mais il faut que l'emtteur et le recepteur (compresseur et decompresseur) soit au courant de cette table...
(la moyenne n'est pas forcement codé ainsi)

bien sur vous voyez aussi que ce compresseur est destructueur, impossible de coder un valeur de 11, ici on prendra 8 (le + proche)
et imaginé que vous vouliez passez de 0 a 127, il faudra alors 4 echantillons, donc un temps de reaction tres long pour les grande differentielles...

bref, cette methode de compression est quand meme efficasse et dechire moi le son que d'echantilloné a 4000ko ou de prendre un echantillons sur 2...
les debit peut etre divisé par 1,5 voir 2
(nteraissant pour un multi chat vocal ;) )

une fois ceci fait, vous pouvez aussi passez un coup de RLE (run lentgh encoding) qui a pour role deremplacer
une longue serie de zero (binaire) par une balise et ou un indice en debut de buffer...
(moi j'ai mis un indice et le nb de zero dans le debut de l'envois du buffer

avec le rle, vous divisez par 2 voir 3 les debit soit 4Ko a 2 Ko...

voila j'espere que vous avez captez, bien codé ca prend pas enormement de ressources...
(j'ai triché , j'ai codé en c++ la manip des bit, en vb je sait pas faire ou alors trop couteux en patate))

bref, moi actuelment je cherche a mettre un coup de fft la dessus, ainsi
je pensse pouvoir descende en dessous du 1.5 ou 1 Ko
(sympa pour les modem ;) ...)

A++
grosiflex Messages postés 19 Date d'inscription jeudi 4 octobre 2001 Statut Membre Dernière intervention 21 octobre 2004
27 févr. 2003 à 19:20
ce truc sert a montrer la base du stream,
avec wimm et 2 sockets, franchement tu peux streammer test propres echantillon, comme tu le sents winmm est fait pour ca hex_man matte quelque doc la dessus, tu verra c'est simple
winmm est un point d'entree et sortie qui te permet de filer ou de recuperer de windows des buffer's plein'd 'octets'
apres a toi de les faire passer dans les tuyaux (socket ou autres) comme tu le sents
dure de controler + que ca en vb sans que ce soit trop incomprehenssible...

Approche Winmm:
---------------
en fait la dll winmm.dll est dispo dans depuis les 95 dans les windows,
dans cette dll vous trouvez donc un enssemble de fonction et d'adresse pour echanger de l'info
avec votre matos audio. (l'interet c'est compatibilité, et control 'Bas niveau' des octets sonor)
l'utilisation est assez facile:

vous allez balancez des données ou en recevoir de winmm, par l'intermediarede buffers, ces buffers contiennent, les donéess du son et des données propres a winmm (taille du buffer, format, etc..)
winmm est decomposée en 2 jeux (buffers et fonctions): IN et OUT
pour l'utilisez l'un ou lautre il faut:
-ouvrir le matos sonor (in ou out)
-balancer ou recuper les info
-fermer le matos sonor

pour ouvrir le periph d'entree ou sortie (idem):
-1/ choisir un nom fixe de buffer pour winmm
-2/ preparer son format audio (96Khz, 16 bits ou autre...)
-3/ preparer les buffers (allouer la memoire,position des flag,format,etc..)
-4/ Passer le pointeur vers les buffer a winmm
-5/ lancer l'ouverture (aquisition ou lecture)
-6/ verifier l'ouverture

pour fermer le periph d'entree ou sortie (idem):
-1/ DE-prepare les buffer (vire les pointeru de winmm)
-2/ on desaloue la memoire
-3/ on ferme le periph

Winmm remplie le buffer un a un (ou joue le son des buffer un a un) suivant
l'etat du flag

IN:
---
pour utiliser le periphe en in:
1/ scruter tous les buffer 1 par 1
2/ matter leur flag
3/ si le buffer est pres, recuperer les infos du buffer courant et le balancer dans le sock ou autre
4/ mettre le buffer comme dispo
5/ recommencer a l'infini ^^ !!

OUT:
---
pour utiliser le periphe en in:
1/ scruter tous les buffer 1 par 1
2/ matter leur flag
3/ si le buffer est dispo, remplire ce buffer des octets du son a jouer provenant du socket ou autre..
4/ mettre le buffer comme 'pres a etre joué'
5/ recommencer a l'infini ^^ !!


voila comment ca s'utilise, mattez le module MWinMM dans le source vous trouvez ainsi les rapport
entre explication et nom de fonctions et etat des flags. dans ce module un enssemble de fonction est dispo pour facilement
utiliser winmm, (exemple lecteur vraiement perso (a vous de coder les filtres et tous...)

avec winmm vous avez le controle total du matos...


c'est po tres dure
hex_man Messages postés 28 Date d'inscription mercredi 21 novembre 2001 Statut Membre Dernière intervention 12 décembre 2007
27 févr. 2003 à 12:52
nikel ta source ;) j'avous symaptoche , moi aussi je cherchais un truc comme ça mais , je cherchais plutot comment streamer moi m^m les echantillon audio sans passer par des ocx ou dlls, si t'as des info je susi preneur merci ;)
grosiflex Messages postés 19 Date d'inscription jeudi 4 octobre 2001 Statut Membre Dernière intervention 21 octobre 2004
26 févr. 2003 à 20:27
merci pour la note, et pour les mail, c'est sympo...
mattez aussi une variante de la combox ici:
http://www.combox.fr.st
A++
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
25 févr. 2003 à 19:54
C'est excelent, vraiment ! ça faisait longtemps que je cherchait une source comme ça pour communiqué en lan et ça marche du tonnerre !

Bon j'avoue l'echantillonnage est bidon mais on peut encore l'amelioré sans passé par le c

Bon... 7 pour la source + 2 parce que ça me rend service

continue

b@nne prog
Rejoignez-nous