Moteurs audio, 32 bits / 64 bits, distinguer le vrai du faux .
- 185 réponses
- 23 participants
- 28 379 vues
- 31 followers

Aegan

voilà, je me pose la question suivante :
a-t-il déjà été fait un comparatif sérieux des moteurs audio qui animent les DAWs les plus réputées (ou les plus répendues ...) ?
Depuis quelques temps, on voit apparaître comme principal argument de renouvellement de certains logiciels, le fait que leur moteur audio passe au 64 bits. Y'a-t-il un gain réel à se lancer dans le 64 bits en tant que moteur de mixage (et pas en tant que moteur de système d'exploitation ...
 ) ?
 ) ?Personnellement, je pense bien qu'il doit y avoir un avantage net puisque nous massacrons joyeusement de plus en plus le signal à coup de plug-ins déjantés, et qu'une précision accrue dans les calculs permet de conserver une cohérence dans le signal traité (ne serait-ce qu'au niveau de sa phase ...). Sans compter que des logiciels aux ambitions très modestes comme Tracktion 2 se sont armés de ces moteurs 64 bits, alors que des plates-formes considérées comme "haut de gamme", comme ProTools, pour ne pas le citer, en reste pour l'instant au 32 bits (alors que ses prétentions qualitatives et pécuniaires sont pour le moins beaucoup plus élevées). Et en outre, des logiciels comme Samplitude ou Pyramix ont des moteurs en 32 bits mais extrêmement réputés (car très bien programmés semble-t-il) pour leur respect du signal. Une vache n'y retrouverait pas son veau ...
Un rapide état des lieux :
moteurs 64 bits :
Sonar 6
Cubase 4
Sequoia 9
Tracktion 2
moteurs 32 bits : (je vais en oublier c'est sûr)
Samplitude 9
Pyramix 5
Nuendo 3
Pro Tools ??? (je me perds dans les versions)
Kristal Audio Engine (faudrait pas oublier les gratuits ...)
voilà, merci à ceux qui voudront bien partager cette réflexion avec moi ...


Will Zégal

Hors sujet : Jan : oui, tout à fait. On a demandé à avoir le choix d'un autre truc un peu moins sévère pour les messages moins "gros yeux", mais pour l'instant, on a pas.
Donc, on poste en "normal" ou en rouge. Pas d'intermédiaire.
Il me semblait important de recadrer un peu modéro staïle, là. Avant que ça ne parte en c... ;)
Les passionnés ont parfois le sang chaud (Panca)  
 

Will Zégal

Quelle est l'explication technique de ce phénomène ?

Est-ce lié au nombre de pistes présentes dans le projet ou au nombres de pistes actives ?
Par exemple, je bosse sous Sonar où l'on peut désactiver (archiver) des pistes. C'est différent du mute. Plutôt une sorte de freeze qui rend la piste totalement inopérante tant qu'on ne la "désarchive" pas.
Comme je conserve souvent les prises multiples de cette façon assez loin dans le projet, ça peut faire une grosse différence à la longue.

Anonyme

Citation : Par contre, si vous pouviez développer cette histoire de dB perdus par piste... 
J'avoue que c'est la première fois que j'en entends parler.  
 
Et il me semble que ça reste dans le sujet, ça 
 
 Numérique = calcul en base 2. OK ?
Les mots numériques, ou informatique comportent un nombre limité et défini de bits, soit en audio, 24 signifiants pour les fichiers wav par exemple (standard pro actuellement).
Partons, pour les besoins de la démo, d'un mot de 1 bit. Si nous ajoutons deux mots de 1 bits, nous pouvons avoir ces résultats :
0+0=0
0+1=1
1+0=1
1+1=2
Mais dans le dernier cas, comme nous sommes en binaire, on a besoin de deux bits pour coder ce "2", nous le notons 10. Dans le cas d'un moteur audio (t'as vu, je reste bien dans les clous ;) ) Ce 10 est une saturation s'il ne peut pas gérer des mots de plus de un bit. On peut étendre cette démo à 8 bits, ou 16 ou 24, le problème reste le même.
Il n'y a dans ce cas que deux solutions, soit permettre au moteur audio de travailler sur plus de bits que n'en comportent les mots fournis par les pistes, c'est ce que fait ProTools (on l'a vu, seulement les bus de sommation), ou s'arranger pour ne jamais se trouver dans la situation d'avoir besoin d'un bit supplémentaire. Les moteurs en 32bits float, on contourné le problème en ajoutant 8 bits de codage de virgule permettant de "décaler" le calcul, si on a besoin de ce 25ème bit, il le donne et celui-là devient le MSB (Most Significant Bit), et en échange, il te pique le bit de poids le plus faible LSB (Less Significant Bit). A l'arrivée, tu n'a pas saturé, mais le résultat est toujours sur 24 bits signifiants.
JM

Anonyme

Citation : Est-ce lié au nombre de pistes présentes dans le projet ou au nombres de pistes actives ?
Ni lun ni l'autre mon modo adoré, c'est simplement comme expliqué précédemment, que la sommation ne peut pas dépasser le OdBfs à l'arrivée, et que ce 0dBfs correspond à la valeur la plus grande du mot, codé avec le nombre de bit adéquat.En pratique, que ce soit en analogique ou en numérique, la qualité intrinsèque du système conserve les mêmes caractéristiques pour un mix de deux pistes ou deux cent pistes. Le résultat final devrait toujours avoir les qualité inhérentes à la résolution choisie, mais cela ne garantie pas la conservation de la qualité d'origine de chaque piste. Pour ça il faudrait un système capable d'agglomérer les bits à l'infini.
Par exemple, si tu mélanges une piste à 0, avec des crètes à 0dBfs, et une autre à -80dB, pour conserver la qualité originale de cette piste, il faudrait une dynamique de 144+80=224dB, soit une résolution de 38bits. Tu imagine ce que cela donne sur un fade out ? Et bien, un bug dans le pentium a fait, il y a deux ans environ, que c'est un peu ce qui se passait sur les logiciels natifs en 32bits, cela s'appelait la dénormalisation. Le CPU essayait en quelque sorte de conserver les 24 bits de résolution jusqu'en bout de course des faders, ou au bout des queues de réverbe, du coup, en fin de lecture d'une session, le CPU se retrouvait au taquet et plantait la machine.
JM

Anonyme

Hors sujet :  Citation : Par exemple, je bosse sous Sonar où l'on peut désactiver (archiver) des pistes. C'est différent du mute. Plutôt une sorte de freeze qui rend la piste totalement inopérante tant qu'on ne la "désarchive" pas. 
 
Comme je conserve souvent les prises multiples de cette façon assez loin dans le projet, ça peut faire une grosse différence à la longue.
JM

Anonyme

Hors sujet :  Citation : Le topic m'a semblé suffisamment intéressant et de bonne tenue pour avoir l'honneur de figurer comme "topic de la semaine" dans la newsletter hebdomadaire.  
 
JM

Will Zégal

 
 Merci very much. C'est tout con quand c'est si bien expliqué

Hors sujet : Faut pas ! Faut pas !
C'est juste la raçon de la gloire

Anonyme

Hors sujet : T'as de la chance, en me relisant j'ai vu que j'avais laissé une belle coquille, c'est corrigé. C'est à propos du moteur ne pouvant gérer les mots de plus de un bit, message 129. J'avais écrit "ne pouvant gérer les mots de plus de deux bits", ce qui rendait le paragraphe abscon.
JM

Will Zégal

Hors sujet : Pas vu la coquille et je ne la vois toujours pas (enfin, sa correction).
J'ai dû faire un "nos lecteurs auront rectifié d'eux-même" 
[ Dernière édition du message le 05/07/2011 à 10:59:03 ]

Will Zégal

Citation : Le résultat final devrait toujours avoir les qualité inhérentes à la résolution choisie, mais cela ne garantie pas la conservation de la qualité d'origine de chaque piste. Pour ça il faudrait un système capable d'agglomérer les bits à l'infini.
Selon cette logique (que du simple bon sens sans l'appui de la connaissance technique m'avait laissé deviner), ça veut dire que plus le séquenceur travaille avec une résolution poussée, meilleure est la qualité finale.
Donc, théoriquement 16 bits < 24 < 48 < 64 < 128...
Sauf qu'on tombe à la longue sur deux écueils :
1- la puissance de traitement des systèmes mise à rude épreuve par des calculs plus complexes et de plus grandes quantités de donner à gérer
2- la limite de l'oreille humaine qui fait que ça ne servirait à rien de pousser la qualité jusqu'à des différences de toutes façons inaudibles.
à quoi on peut éventuellement ajouter
3- la limite (notamment numérique, cf CD 16/44.1) des systèmes de reproduction qui fait qu'il ne sert pas à grand chose de mixer avec une "qualité" d'un niveau tel qu'il disparaîtra lors du passage sur support de reproduction. Sauf que ceux-ci évoluent et qu'on ne sait pas que seront les standards dans 20 ou 30 ans. Déjà, on a des standards plus précis que le CD.
Pour péréniser ses zoeuvres zimpérissables, il peut donc être préférable (de lièvre) de travailler d'ores et déjà à de hautes résolutions, même si ça ne suit pas (encore) côté reproduction.
J'ai bon ?


Anonyme

Ensuite, éventuellement un surplus de résolution pendant le calcul, mais à l'arrivée, je pense que le 24 bits et ses 144dB de dynamique devraient suffire ;).
JM
Hors sujet : PS : Bon, je vous laisse, il faut que j'aille chercher du vermifuge pour mon chat

Will Zégal

Hors sujet : Y'a pas le feu.
Ceci est un forum, pas un chat  
 
(même s'il a aussi parfois besoin d'être vermifugé)
Pour la logique consistant à mixer à une résolution supérieure que celle du support final, je pense que c'est acquit pour tout le monde, non ?
Par contre, reste la question de départ : jusqu'où aller ?
Personnellement, je travaille tout en 24/96 pour la résolution de fichiers. Je n'ai pas coché la case « mixage en 64 bits » dans mon Sonar because ressources et je pense que le problème actuel de qualité de son est plus crutial sur mes compétences que le « moteur audio » de mon soft.
Je fais bien (sur mes enceintes de monitoring) la différence entre 44 et 96 k, mais je doute de pouvoir répondre sur des tests en aveugle entre du 16 et du 24 bits.
Bref, selon les résultats de votre discussion, il semble préférable quand on le peut de mixer en 64 bits, mais il ne semble pas utile que les systèmes montent à 128 bits à l'avenir. Me trompé-je ?

Anonyme

personnellement, en general, je travaille en 24/48 le plus souvent, en entrée, les 24 bits, c'est vraiment un grand confort, ça evite de limiter les prises et de devoir se mettre au taquet pour avoir une dynamique exploitable.

Anonyme

Citation : Bref, selon les résultats de votre discussion, il semble préférable quand on le peut de mixer en 64 bits, mais il ne semble pas utile que les systèmes montent à 128 bits à l'avenir. Me trompé-je ?
Je ne me suis pas prononcé, car je ne sais pas encore comment sont utilisés les 64bits.JM

Pov Gabou

Citation : 
'est quoi cette blague?? latence midi?? 7 ms?? 
C'est pas une blague du tout. Le midi, si tu l'utilises a travers les ports standards, c'est du 30000 bauds en gros, si mes souvenir sont bons, cad quelques 4 ko/s en gros. Un message Midi pour une note necessite au moins 3 octets, de memoire la aussi: un pour le channel + type de message, un pour la note jouee, et un pour l'amplitude. Ca fait donc presque une ms pour envoyer une note avec un cable midi standart. Si tu joues plusieurs notes, tu peux vite arriver a plusieurs ms.
Citation : 
Donc, théoriquement 16 bits < 24 < 48 < 64 < 128... 
Deja, le 16 et 24 bits dont on parle sont en representation *fixe*, cad que la precision depend de la dynamique, contrairement aux representations en flottant (celles qui sont en 32 et 64 bits, en general). Le 128 bits flottant n'existe pas sur les cpu courants (ni mac, ni PC; on peut emuler le 128 bits, mais ce serait extremement lent, je pense au moins 10 voire 100 fois plus lent); le standart de representation flottante pour le 128 bits est en train d'etre discute, donc je pense que sur pc, il faudra attendre au moins 10 ans pour les voir venir.
Bref, on peut pas comparer du tout comparer des resolutions entre elles si elles sont de representation differente (fixe ou flottante).
Citation :  
Personnellement, je travaille tout en 24/96 pour la résolution de fichiers. Je n'ai pas coché la case « mixage en 64 bits » dans mon Sonar because ressources et je pense que le problème actuel de qualité de son est plus crutial sur mes compétences que le « moteur audio » de mon soft. 
 
Je fais bien (sur mes enceintes de monitoring) la différence entre 44 et 96 k, mais je doute de pouvoir répondre sur des tests en aveugle entre du 16 et du 24 bits. 
Bref, selon les résultats de votre discussion, il semble préférable quand on le peut de mixer 
Je pense que mixer en 64 bits est une connerie dans 99 % des cas, si ce n'est pas 100 %. Deja, je sais que moi, je fais pas la difference, et meme entre developpeurs, il y en a beaucoup qui sont pas persuades de l'utilite.
Ensuite, le 16 bits peut souvent suffir si tes sources sont d'excellente qualite. Il faut bien comprendre, j'insiste sur ce point, que tes fichiers en 16 bits font etre tranformes en 32 bits des l'instant ou tu vas les mixer dans ton sequenceur. La ou le 24 bits compte beaucoup aussi, c'est lorsque tu vas utiliser le resultat avec un autre outil plus tard. Pour le support final, par contre, je suis pas super persuade de l'interet en general. Le probleme du 16 bits, c'est que la resolution 16 bits n'est valable que si ton signal est proche du 0 dB; si ton signal est a -40 dB par exemple, tu perds beaucoup en dynamique et en precision (c'est difficile de dire combien, car des que tu t'eloignes du 0 dB avec 16 bits, tres vite l'hypothese du bruit de quantification independant de la source n'est plus verifiee, ce qui la formule 1 bits = 6 dB caduque, et rend les calculs tres difficiles).
Le coup de perdre de la resolution avec le mixage pur, c'est du delire integral a mon avis: oui, en theorie, tu as de la perte, mais c'est totalement ridicule par rapport a tous les autres parametres qui peuvent compter pour le son. Par exemple, le fameux probleme de denormalisation, concerne les valeurs tres proches de 0: dans ce cas, c'est un peu diffent. Ces petits nombres sont ridiculeusement petits, et totalement insignifiant pour de l'audio
Je fais un petit rappel: un nombre flottant en 32 bits est represente comme ca (sur powerpc, intel, etc... C'est un standart, IEEE 754):
nombre = s * 2^e * m
Ou s est 1 ou -1 (pour faire la distinction negatif positif), e est un chiffre code sur 8 bits qui va entre -127 et 126, et m est un chiffre entre 1 et 2 (strictement inferieur a 2), code sur le reste, cad 32 - 8 - 1 = 23 bits.
En general, les signaux sont supposes etre entre +1 et -1 (c'est le 0 dB; on peut depasser le 0 dB, par exemple entre plug in, pour faire par exemple de l'overdrive, mais a la fin, quand le signal est converti pour aller vers la carte sonore, tout ce qui est au dela de [-1, +1] est distordu numeriquement, sauf si l'hote fait de la bidouille a ce niveau la; on peut imaginer que differents hotes aient differents comportements a ce niveau la).
Dans cette representation, dite normale, le plus petit nombre representable est de l'ordre de 10^-38. Pour les nuls en maths, ca veut dire qu'on a une dynamique a ce niveau la de ... 740 dB ! Ce chiffre ne veut pas dire grand chose, cependant, car ce qui importe en general, c'est le plus petit nombre representable comme une difference, cad concretement: quelle est la plus petite difference possible entre deux nombres donnes, et la, c'est de l'ordre de 1e-7 (1.2209290e-7 pour etre precis), ce qui donne alors 140 dB en gros de precision. Si on passe au denormal, la representation est differente (e est fixe a -126, et au lieu d'avoir m etre 1 et 2, m est entre 0 et 1, et permet d'aller jusqu'a 10^-45.
Mais il faut bien se rendre compte d'une chose: si on mixe une piste a 0 dB et une a -80 dB (ce qui est stupide en general, mais passons), on utilise encore tous les bits de precision (les 23), c'est essentiellement sur e que ca se joue, donc on perd vraiment quasiment rien, voire rien du tout. Surtout qu'en interne, au moins sur Intel, les calculs intermediaires sont faits sur 80 bits, mais je sais pas vraiment comment. Entre autre, je connais pas le format de representation. Mais rien qu'en 64bits, faut voir qu'on a a deja plus de 6000 dB de difference entre le plus petit nombre et 1, et au pire 300 dB de dynamique entre n'importe quelles valeurs).
Donc ce que dit Jan est que partiellement exact sur son exemple de sommation, je pense.

Anonyme

Citation : Mais il faut bien se rendre compte d'une chose: si on mixe une piste a 0 dB et une a -80 dB (ce qui est stupide en general, mais passons), on utilise encore tous les bits de precision (les 23),
Mais non mon Pov Gabou, c'est vrai pour le résultat de la sommation, mais ça ne l'est pas en ce qui concerne la résolution de chacune des pistes.Nous sommes bien d'accord que dans le monde du 32 bits flottant, la résolution réelle est de 24 bits. La piste à -80dB conserve jusqu'à la sommation sa résolution de 24bits, mais une fois ajoutée à une autre piste dont les crètes sont amenées à 0dBfs, nous somme bien en valeur réelle à -80dB, soit une résolution de 10bits sur les 24 de départ.
Mais je t'accorde que je me suis placé au départ dans un cas d'école, qui ira détecter la perte de qualité de ce son alors que dans le mix il se situe à -80dB ? Mais c'est quand même la situation rencontrée sur les fades out.
Sur la dénormalisation, c'est vrai que c'est un cas un peu particulier, c'est la raison de "c'est un peu ce qui se passait", sinon, j'aurais écrit "c'est ce qui se passait" ;)
JM

Pov Gabou

Citation : 
Mais non mon Pov Gabou, c'est vrai pour le résultat de la sommation, mais ça ne l'est pas en ce qui concerne la résolution de chacune des pistes.
nous somme bien en valeur réelle à -80dB, soit une résolution de 10bits sur les 24 de départ. 
Je comprends pas du tout d'ou tu sors ces 10 bits de precision ?
Je suis pas d'accord sur le fait que tu perdes beaucoup en precision en ayant deux pistes mixees l'une a -80 dB et l'autre a 0 dB. Si en absolu on a une piste qui va entre -1 et 1 (0 dB), et une autre qui va entre -1e-4 et 1e-4 (-80 dB), on va avoir en sommant entre 1 et -1. Donc dans le resultat final, on a au pire seulement 1e-7 d'amplitude de resolution, ce qui fait encore 60 dB sur le signal a -80 dB, et bien les 140 et quelques sur le resultat final... Et la sommation est faite a la fin de toute facon, avant que ce soit passe a la carte sont (qui elle n'a que 24 bits de precision au mieux), sur une representation fixe.
Ah, je vois d'ou tu peux sortir ces 10 bits de precision: 1 bit de precision donne 6 dB de dynamique ? Attention, cette regle est totalement fausse en representation flottante, qui n'est pas lineaire du tout.

Pov Gabou

Citation : 
#! /usr/bin/env python                                                                   
# Last Change: Mon Oct 30 01:00 PM 2006 J                                                
import numpy as N
    
n   = int(1e5)
dbd = -80
    
# A is double, between -1 and 1 (0dB)                                                    
A   = 2*N.random.rand((n))-1                                                             
# B is double, between -1e-4 and 1e4
B   = (2*N.random.rand((n))-1) * 10 ** (dbd/20)                                          
    
S   = A + B
        
powerA  = N.sqrt(N.sum(A**2)) * 1./n                                                     
powerB  = N.sqrt(N.sum(B**2)) * 1./n                                                     
print "Real db Diff (power) is %f" % (20*N.log10(powerA/powerB))                         
    
A32 = N.float32(A)
B32 = N.float32(B)                                                                       
    
S32     = A32 + B32
    
# numpy broadcast to 64 bits automatically, so the difference is done
# in 64 bits
diff    = S32 - S
powerdiff   = N.sqrt(N.sum(diff ** 2)) * 1./n
maxdiff     = N.max(N.abs(diff))
                                                                                         
print "average diff of dynamic compared to bigger signal (0 dB) is %f" % (20*N.log10(powerdiff))
print "worse dynamic compared to bigger signal (0 dB) is %f" % (20*N.log10(maxdiff))
Et ca me donne autour de 220 dB de dynamique pour la difference entre 32 bits et 64 bits summing, et la pire valeur sur 100000 echantillons est encore a 144 dB.
Et comme je suis motive, j'ai fait la meme chose en C, pour essayer de plus grosses valeurs et pour que tout le monde puisse essayer (attention, c'est programme a la hache, donc ca prend pas mal de memoire. Sur mon pc du labo, j'ai 2 Go de ram avec 3 de swap, le programme doit consommer autour de 10^7 * 8 * 8 octets, ce qui fai en gros 640 Mo).
Citation : 
/*
 * Last Change: Mon Oct 30 01:00 PM 2006 J
 *
 * Small test to see pratical difference beween summing in 32 and summing in 64 bits
 * on the platform where this program is run
 */
/*
 * For ISO C, all floating functions are for double by default.
 * If they have the suffix f, they are float
 */
/* For FLT_ constants */
#include <float.h>
/* for drand48 (SVID standart) and exit */
#include <stdlib.h> 
/* for log10 */
#include <math.h>
#include <stdio.h>
int do_compare(size_t nelements, double dbd);
int generate_signals(double *in, double *in2, size_t nel, double dbdiff);
int lev2dB(double ref, double val, double* ret);
double db2coeff(double dblev);
double avdbdiff(const double* ref, const double* val, size_t nel);
double avdbref(const double* in, size_t nel, double ref);
double mindbref(const double* in, size_t nel, double ref);
long double power(const double*in, size_t nel);
int sum32(const float* in1, const float* in2, float* out, const size_t n);
int sum64(const double* in1, const double* in2, double* out, const size_t n);
int diff64(double* inout, const double *in2, size_t nel);
int double2float(const double* in, float *out, size_t nel);
int float2double(const float* in, double* out, size_t nel);
/* alloc or die */
void*    xmalloc(size_t n);
/* Not sure about precision, but should not matter, since 
 * it is used only for db computation*/
double exp10(double in)
{
    return exp(in * log(10));
}
/* Entry point */
int main(void)
{
    int     status;
    size_t  nel = 10000000;
    double  dbdiff  = -80;
    status  = do_compare(nel, dbdiff);
    if (status < -1) {
        fprintf(stderr, "Error while comparing...n");
        return -1;
    }
    return 0;
}
int do_compare(size_t nel, double dbd)
{
    double  *a, *b, *s, *s64;
    float   *a32, *b32, *s32;
    int     status;
    double  sumdbdiff;
    /*
     * Allocations
     */
    a   = xmalloc(sizeof(*a) * nel);
    b   = xmalloc(sizeof(*b) * nel);
    s   = xmalloc(sizeof(*s) * nel);
    a32 = xmalloc(sizeof(*a32) * nel);
    b32 = xmalloc(sizeof(*b32) * nel);
    s32 = xmalloc(sizeof(*s32) * nel);
    s64 = xmalloc(sizeof(*s64) * nel);
    srand48(time(0));
    /*
     * Generate test signals
     */
    status  = generate_signals(a, b, nel, dbd);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    /*
     * Make a copy of test signals into 32 bits buffers
     */
    status  = double2float(a, a32, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    status  = double2float(b, b32, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    /*
     * Do the summation in 32 bits
     */
    status  = sum32(a32, b32, s32, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    status  = float2double(s32, s64, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    /*
     * Do the summation in 64 bits
     */
    status  = sum64(a, b, s, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    /*
     * Compute the difference (in 64 bits) (in place into s)
     */
    status  = diff64(s, s64, nel);
    if (status) {
        fprintf(stderr, "%s:%s, %d errorn", __FILE__, __func__, __LINE__);
        exit(EXIT_FAILURE);
    }
    /*
     * Compare the results
     */
    sumdbdiff = avdbref(s, nel, 1.0);
    printf("average db diff between 32 bits summing and 64 summing is %fn", sumdbdiff);
    sumdbdiff = mindbref(s, nel, 1.0);
    printf("worse db diff between 32 bits summing and 64 summing is %fn", sumdbdiff);
#if 0
#endif
    /* Those free are just for checking under valgrind */
    free(a);
    free(b);
    free(s);
    free(a32);
    free(b32);
    free(s32);
    free(s64);
    return 0;
}
/* compute the power of in: 1/nel * sqrt(sum(in ** 2)) */
long double power(const double*in, size_t nel)
{
    long double acc = 0;
    size_t      i;
    for(i = 0; i < nel; ++i) {
        acc += in[i] * in[i];
    }
    return sqrtl(acc) / nel;
}
int diff64(double* inout, const double *in2, size_t nel)
{
    size_t      i;
    for(i = 0; i < nel; ++i) {
        inout[i] -= in2[i];
    }
    return 0;
}
/* Generate (uniform) random signals in and in2. in2 has dbdiff dB difference on average 
 * compare to in1, and in1 is normalized in the range [-1, 1] */
int generate_signals(double *in1, double *in2, size_t nel, double dbdiff)
{
    size_t  i;
    double  amp = db2coeff(dbdiff);
    for(i = 0; i < nel; ++i) {
        in1[i]  = 2 * drand48() - 1;
        in2[i]  = amp * (2 * drand48() - 1);
    }
    printf("Asked level is %f, real level on average is %fn", dbdiff, avdbdiff(in1, in2, nel));
    return 0;
}
/* Convert a and b content to 32 bits and put the results into a32 and b 32.
 * I am not sure about the correct way to do the convertion... */
int double2float(const double* in, float *out, size_t nel)
{
    size_t  i;
    for(i = 0; i < nel; ++i) {
        out[i]  = (float)in[i];
    }
    return 0;
}
int float2double(const float* in, double* out, size_t nel)
{
    size_t  i;
    for(i = 0; i < nel; ++i) {
        out[i]  = (double)in[i];
    }
    return 0;
}
/* give the *average* db level compared to a reference 0 dB */
double avdbref(const double* in, size_t nel, double ref)
{
    long double pow;
    double      dbl;
    
    pow = power(in, nel);
    lev2dB(ref, (double)pow, &dbl);
    printf("ref is %10e, pow is %10e, level is %fn", 
            ref, (double)pow, dbl);
    return dbl;
}
/* give the min db level compared to a reference 0 dB */
double mindbref(const double* in, size_t nel, double ref)
{
    double  maxval;
    double  tmp;
    double  dbl;
    size_t  i;
    maxval  = 0;
    for(i = 0; i < nel; ++i) {
        tmp = fabs(in[i]);
        if ( tmp > maxval) {
            maxval  = tmp;
        }
    }
    
    lev2dB(ref, maxval, &dbl);
    printf("ref is %10e, max is %10e, level is %fn", 
            ref, maxval, dbl);
    return dbl;
}
/* give the *average* db difference between two signals */
double avdbdiff(const double* ref, const double* val, size_t nel)
{
    long double pow1;
    long double pow2;
    double      dbl;
    
    pow1    = power(ref, nel);
    pow2    = power(val, nel);
    lev2dB((double)pow1, (double)pow2, &dbl);
    printf("pow1 is %10e, pow2 is %10e, dbdiff is %fn", 
            (double)pow1, (double)pow2, dbl);
    return (dbl);
}
/* put the db value with reference level ref into ret
 * return 0 on success, -1 otherwise */
int lev2dB(double ref, double val, double* ret)
{
    if (fabs(val) < DBL_EPSILON || val < DBL_MIN) {
        fprintf(stderr, "%s:%s, line %d, val (%f) is below epsilon or negativen", 
                __FILE__, __func__, __LINE__, val);
        return -1;
    }
    *ret    = 20*log10(ref / val);
    return 0;
}
/* given a dB level difference, returns the amplitude coeff */
double db2coeff(double dblev)
{
    return exp10(dblev / 20.);
}
/* sum in 32 bits */
int sum32(const float* in1, const float* in2, float* out, const size_t n)
{
    size_t  i;
    for(i = 0; i < n; ++i) {
        out[i]  = in1[i] + in2[i]; 
    }
    return 0;
}
/* sum in 64 bits */
int sum64(const double* in1, const double* in2, double* out, const size_t n)
{
    size_t  i;
    for(i = 0; i < n; ++i) {
        out[i]  = in1[i] + in2[i]; 
    }
    return 0;
}
void* xmalloc(size_t n)
{
    void*   tmp;
    tmp     = malloc(n);
    if (tmp == NULL) {
        fprintf(stderr, "Error while allocatingn");
        exit(EXIT_FAILURE);
    }
    return tmp;
}
qui me donne encore une fois autour de 220 dB en moyenne et 141 dB dans le pire des cas sur 10^7 tirages. Je pourrais essayer plus si je me faisais chier a bufferiser au lieu de tout allouer en une fois, mais j'ai pas que ca a foutre non plus

Bref, a moins que je me sois plante quelque part (ce qui n'est pas impossible dans le code C, mais dans le code python, je pense pas trop), le fait que les calculs internes soient faits de toute facon en 80 bits sur un proc intel meme avec des valeurs d'entree/sortie en 32 bits fait qu'on garde bien une precision tres bonne avec du 32 bits, et ce meme dans un cas vraiment extreme (mixage de deux pistes avec 80 dB de difference).

Pov Gabou

Citation : 
#! /usr/bin/env python
# Last Change: Mon Oct 30 01:00 PM 2006 J
import numpy as N
n   = int(1e5)
dbd = -80
# A is double, between -1 and 1 (0dB)
A   = 2*N.random.rand((n))-1
# B is double, between -1e-4 and 1e4
B   = (2*N.random.rand((n))-1) * 10 ** (dbd/20)
S   = A + B
powerA  = N.sqrt(N.sum(A**2)) * 1./n
powerB  = N.sqrt(N.sum(B**2)) * 1./n
print "Real db Diff (power) is %f" % (20*N.log10(powerA/powerB))
A32 = N.float32(A)
B32 = N.float32(B)
S32     = A32 + B32
# numpy broadcast to 64 bits automatically, so the difference is done
# in 64 bits
diff    = S32 - S
powerdiff   = N.sqrt(N.sum(diff ** 2)) * 1./n
maxdiff     = N.max(N.abs(diff))
print "average diff of dynamic compared to bigger signal (0 dB) is %f" % (20*N.log10(powerdiff))
print "worse dynamic compared to bigger signal (0 dB) is %f" % (20*N.log10(maxdiff))
# Now, let's try to get back our little track b:
B32_2   = S32 - A32
diff    = B32_2 - B32
# Check that the computation was done in 32 bits
assert diff.dtype == N.float32
powerdiff   = N.sqrt(N.sum(diff ** 2)) * 1./n
maxdiff     = N.max(N.abs(diff))
print "average diff of dynamic between b before and after summing %f" % (20*N.log10(powerdiff))
print "worse dynamic between b before and after summing %f " % (20*N.log10(maxdiff))
Et la encore, ca me donne a nouveau le resultat de 220 dB en moyenne, et 140 dans le pire des cas, en retrouvant la piste a -80 dB.
Concretement, ca veut dire qu'on aura une bonne chose d'avoir *exactement* les memes fichiers d'export a la fin en 24 bits (ca vaudrait le coup d'essayer, en fait) avec du summing 64 bits et 32 bits

Pov Gabou


Anonyme

Citation : ce qui fait encore 60 dB sur le signal a -80 dB
Ben voilà, 60dB, ça fait combien de bits ?JM

Will Zégal

 
 Mais bravo et merci


Pov Gabou

Citation : 
Ben voilà, 60dB, ça fait combien de bits ? 
Rien du tout, il y a pas de relation simple entre bits et dB, puisque ca depend de la representation ;) J'avais dit dans ma reponse du dessus que dans le cas du flottant, tu peux pas du tout utiliser la regle 1 bit supplementaire donne 6 dB de dynamique, car tu ne rentres pas du tout dans les hypotheses de la formule. Je rappelle que les hypotheses de cette formule, c'est:
- quantification *uniforme*
- bruit de quantification decorrele du signal
En plus, puisque les calculs intermediaires font de touue facon intervenir des registres a 80 bits (ou 64 si on utilise pas la fpu principale, mais la logique sse) sur intel, ce qui rend les calculs theoriques pour le moins compliques (c'est pour ca que j'ai programme le truc a la place).
Tu penses que mon raisonnement est correct sur les examples python ? Entre autre, je me demande si c'est vraiment significatif de retrouver le signal a -80 apres sommation et soustraction ? Je suis pas sur, en fait.

Anonyme

Citation : Attention, cette regle est totalement fausse en representation flottante, qui n'est pas lineaire du tout.
Absolument, je me place comme toi du point de vue du résultat final, soit en 24bits virgule fixe.
Anonyme

 
 JM
- < Liste des sujets
- Charte
 
                            
 
                






