Bonjour
Oui, la version double sera plus lente en 32 bits mais pas en 64 bits. Et l'alignement sur les adresses rendra les floats aussi consommateurs de mémoire pour les deux formats (avec l'activation souvent par défaut de l'alignement des adresses).
Tout cela date un peu. Par exemple, quand on regarde la vidéo (j'ai juste échantillonné la vidéo sans respecter Nyquist et Shannon) on voit des techniques d'optimisation (genre v <<=1; v <<=1; v <<=1; v <<=1; v <<=1;...) qui n'ont plus lieu d'être aujourd'hui.
Salutations
Bonsoir,
j'ai lu cette histoire de LUT, ma foi, pourquoi pas, mais elle sortira d'où, cette table ?
Sinon, j'ai continué à me prendre la tête avec des choses maraboutées, je vous montre :
en partant d'un exemple très léger venant de là avec 3 fichiers, j'ai tout condensé en un seul et les seules modifs que j'apporte concernent la variable Bits_Per_Sample, qu'on rencontre habituellement à 16 mais qui peut prendre la valeur 8, 24, 32 ou 64.
Alors si le code fonctionne au poil avec 16, ça part en vrac complet avec 8 et je n'arrive pas à trouver où, c'est pourquoi je vous appelle à mon secours : voilà les images (réduites) en 16 bits puis en 8 :
et voilà les données remontées par le logiciel qui affiche ces jolies images (16M = 16bitsMono, 8M = 8bitsMono) :
Pourquoi la durée est-elle multipliée par 2, tout comme le Total number of samples ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 File : 16M.wav, 176 444 bytes SubChunkSize : 16 Audio format : $0001 (1 = PCM, uncompressed) Channels : 1 SampleRate (samples/s) : 44100 Byte rate (bytes/s) : 88200 Block align : 2 Bits per sample : 16 Size of data block (bytes) : 176400 Total number of samples : 88200 Number of samples per channel : 88200 Duration (s) : 2.0 File : 8M.wav, 176 444 bytes SubChunkSize : 16 Audio format : $0001 (1 = PCM, uncompressed) Channels : 1 SampleRate (samples/s) : 44100 Byte rate (bytes/s) : 44100 Block align : 1 Bits per sample : 8 Size of data block (bytes) : 176400 Total number of samples : 176400 Number of samples per channel : 176400 Duration (s) : 4.0
Merci pour les retours,
Le code du prog :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 /* A simple sound library for CSE 20211 by Douglas Thain (dthain@nd.edu). This work is made available under the Creative Commons Attribution license. https://creativecommons.org/licenses/by/4.0/ For course assignments, you should not change this file. For complete documentation, see: http://www.nd.edu/~dthain/courses/cse20211/fall2013/wavfile */ #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <errno.h> #include <inttypes.h> #define SAMPLES_PER_SECOND 44100 const int NUM_SAMPLES = (SAMPLES_PER_SECOND * 2); struct wavfile_header { char riff_tag[4]; int riff_length; char wave_tag[4]; char fmt_tag[4]; int fmt_length; short audio_format; short num_channels; int sample_rate; int byte_rate; short block_align; short bits_per_sample; char data_tag[4]; int data_length; }; FILE * wavfile_open( const char *filename ) { struct wavfile_header header; int samples_per_second = SAMPLES_PER_SECOND; // int bits_per_sample = 16; int bits_per_sample = 8; strncpy(header.riff_tag,"RIFF",4); strncpy(header.wave_tag,"WAVE",4); strncpy(header.fmt_tag,"fmt ",4); strncpy(header.data_tag,"data",4); header.riff_length = 0; header.fmt_length = 16; header.audio_format = 1; header.num_channels = 1; header.sample_rate = samples_per_second; header.byte_rate = samples_per_second*(bits_per_sample/8); header.block_align = bits_per_sample/8; header.bits_per_sample = bits_per_sample; header.data_length = 0; FILE * file = fopen(filename,"wb+"); if(!file) return 0; fwrite(&header,sizeof(header),1,file); fflush(file); return file; } void wavfile_write( FILE *file, short data[], int length ) { fwrite(data,sizeof(short),length,file); } void wavfile_close( FILE *file ) { int file_length = ftell(file); int data_length = file_length - sizeof(struct wavfile_header); fseek(file,sizeof(struct wavfile_header) - sizeof(int),SEEK_SET); fwrite(&data_length,sizeof(data_length),1,file); int riff_length = file_length - 8; fseek(file,4,SEEK_SET); fwrite(&riff_length,sizeof(riff_length),1,file); fclose(file); } int main() { short waveform[NUM_SAMPLES]; double frequency = 440.0; int volume = 32000; int length = NUM_SAMPLES; int i; for(i=0;i<length;i++) { double t = (double) i / SAMPLES_PER_SECOND; //pour 16bits waveform[i] = volume*sin(frequency*t*2*M_PI); waveform[i] = 127 + (volume*sin(frequency*t*2*M_PI)); } FILE * f = wavfile_open("essai_onefile.wav"); if(!f) { printf("couldn't open essai_onefile.wav for writing: %s",strerror(errno)); return 1; } wavfile_write(f,waveform,length); wavfile_close(f); return 0; }
J'ai juste survolé ton code, dès la ligne 93 «rien ne va plus».
En 8bits, le type ne devrait pas être un short mais quelque chose comme un signed (unsigned) char. D'où deux fichiers de même taille.
Et deux lignes plus loin, l'amplitude. Elle ne doit pas excéder 127 ou 255. D'où (avec ce qui précède) ton effet électroencéphalogramme.
Il faut que tu regardes ta doc, il y a un problème de signature sur le format 8bits mais je ne sais plus de quel ordre.
Le compileur t'aide en te disant l'erreur et te dit quoi choisir(j'ai juste affiché tes valeurs)
Effectivement, sin te retourne 1 double, et donc toi tu le mets dans 1 tableau de short
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 main.cpp: In function int main(): main.cpp:26:12: warning: format %d expects argument of type int, but argument 2 has type double [-Wformat=] 26 | printf("%d\n", (127.0 + (volume * sin(frequency * t * 2 * M_PI)))); | ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | int double | %f![]()
D'ailleurs il y a 1 note sur la page internet "Bitshifting to divide will give you unexpected results for negative numbers. Use actual divide instead."
Effectivement sur les nombres négatifs cela marche moins bien: soit le signe saute/ gêne (il faut sûrement le "masquer") soit avec 1 complément à 1/ complément à 2 cela doit donner des valeurs "inattendues"
Salut les copains, et merci de vous pencher sur ma souffrance :
J'ai utilisé unsigned char et il y a du mieux (duration, number of samples),
J'ai donc modifié ainsi (juste les bouts concernés) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 File : essai_onefile.wav SubChunkSize : 16 Audio format : $0001 (1 = PCM, uncompressed) Channels : 1 SampleRate (samples/s) : 44100 Byte rate (bytes/s) : 44100 Block align : 1 Bits per sample : 8 Size of data block (bytes) : 88200 Total number of samples : 88200 Number of samples per channel : 88200 Duration (s) : 2.0
Exemple de progression (la fin de l'exécution du binaire) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 // int bits_per_sample = 16; int bits_per_sample = 8; //void wavfile_write( FILE *file, short data[], int length ) void wavfile_write( FILE *file, unsigned char data[], int length ) { // fwrite(data,sizeof(short),length,file); fwrite(data,sizeof(unsigned char),length,file); } int main() { // short waveform[NUM_SAMPLES]; unsigned char waveform[NUM_SAMPLES]; // bps 8 ... int i; for(i=0;i<length;i++) { double t = (double) i / SAMPLES_PER_SECOND; //pour 16bits waveform[i] = volume*sin(frequency*t*2*M_PI); waveform[i] = 127 + round(volume*sin(frequency*t*2*M_PI)); printf( "%d\n", waveform[i]); // valeurs échelonnéees de 1 à 254 mais sans aucun ordre, // aucune logique, aucune progression, ni à l'endroit ni à l'envers }
mais le graphique c'est toujours l'électroencéphalo...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 102 136 27 28 135 87 137 21 248 43 167 103 99 148 244 123 32 221 170
Une idée ?
Vous avec le temps, je suis absent cet aprème,
Merci,
![]()
Si tu ne modifies pas ta ligne 95 comme écrit dans mon message précédent, ta sinusoïde, « elle va marcher beaucoup moins bien, forcément ». De même, je ne sais pas pourquoi tu ajoutes un 127 à ton résultat.
Pas trouvé cette ligne...
Ou alors tu parles de la 93 ? Celle qui ressemble à
? Mais je l'ai modifiée, regarde bien :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 int main() { short waveform[NUM_SAMPLES];
Cette histoire du +127, pas la première fois que je le rencontre : quand on travaille en 8 bits c'est comme ça, l'amplitude va de 0 à 255 (un byte), et d'ailleurs, dans un code en Pascal, on peut lire :
Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 w := 2 * Pi * Frequency; // omega for i := 0 to DataCount - 1 do begin //ex 127 pour être au milieu de l'onde //pli | comme son nom l'indique //ca | | impacte la fréquence //tion | | | SoundValue := 127 + round(Volume * sin(i * w / SampleRate)); Write(SoundValue, SizeOf(Byte)); end;
Et c'est confirmé par mes images (réduites aux 2/3) :
Avec +127 :
Sans :
Merci pour tes retours.
La ligne 95: int volume = 32000;, sa valeur doit être inférieur à 127 (ou 255), essaye avec 100 par exemple.
Et pour ton 127+..., si tu fais amplitude * (sin(...)+1.0), ça donne quoi ?
Plutôt 127 parce que 255 donne la même pagaille que l'image "sans" de mon post précédent.
Et sinon, avec 127,![]()
![]()
Mais attention, avec 127 en volume, ça sature dans Audacity. Avec 126 c'est OK.
J'aurais pu capter plus tôt, mais bon, comme je dis toujours, "quand on a le nez sur le guidon, on ne voit pas le paysage", hé ouais...
La même pagaille que l'image "sans" plus un décalage horizontal.
Essaye avec des valeurs comme 10, 40, 80, ... et vois ce que ça donne sur ton graph.
Bonjour Foetus,
De plus, si jadis les opérations de décalage étaient assez coûteuses et dépendaient d'une unité spécifique (deux décalages ne pouvaient s'enchaîner avec recouvrement du pipe), il y a eu une longue période où le décalage unitaire était très rapide (comme un add) sans que la situation des autres décalages se soient sensiblement améliorée. Je pense que ce code est dans cette période. Depuis, tous les décalages sont rapides, aussi cette astuce n'a plus d'utilité.
En outre, il y a le décalage arithmétique sar (sal aussi mais ce n'est qu'un alias de shl), tout aussi rapide aujourd'hui, qui conserve le signe et donc correspond exactement à une division entière par 2n. Et il y a mieux, il n'est même pas nécessaire de recourir à l'assembleur. Si le compilateur voit une expression entière de type n/16, il ne va pas générer une division mais un sar rax, 4 en supposant que n est dans rax. Je sais que ce n'est pas moral : l'écriture est plus simple et beaucoup plus efficace.
Salut
Bonjour,
mon graphe adaptant l'échelle d'affichage au max disponible, difficile de comparer.
Alors j'ai sorti l'artillerie lourde, j'ai nommé Audacity, et ça donne ça, avec de haut en bas le volume à 10, 30, 50, 80, 110 et 126 :
C'est joli tout plein, isn't it ?
Maintenant, il me reste d'autres tests à faire, en comparant justement ce que sort mon outil vs Audacity configuré avec les mêmes param's.
Si c'est pas pour aujourd'hui, ça sera pour demain, stay tuned !
Et encore merci pour le coup de main,![]()
Bonjour,
J'ai fait quelques modifications et posé quelques questions. La plus importante me semble être la taille NUM_SAMPLES : est-ce 2 secondes de sinusoide, la stéréo ?
Le truc le plus grave me semble l'ordre d'écriture qui suppose a priori qu'on est en 16 bits.
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 /* A simple sound library for CSE 20211 by Douglas Thain (dthain@nd.edu). This work is made available under the Creative Commons Attribution license. <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">https://creativecommons.org/licenses/by/4.0/</a> For course assignments, you should not change this file. For complete documentation, see: <a href="http://www.nd.edu/~dthain/courses/cse20211/fall2013/wavfile" target="_blank">http://www.nd.edu/~dthain/courses/cs...ll2013/wavfile</a> */ #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <errno.h> #include <inttypes.h> #define SAMPLES_PER_SECOND 44100 const int NUM_SAMPLES = SAMPLES_PER_SECOND * 2; // !!! Stéréo ? Entrelacé ? struct wavfile_header { char riff_tag[4]; int riff_length; // !!! pourquoi un format signé ? char wave_tag[4]; char fmt_tag [4]; int fmt_length; // !!! pourquoi un format signé ? short audio_format; short num_channels; // !!! pourquoi un format signé ? int sample_rate; // !!! pourquoi un format signé ? int byte_rate; // !!! pourquoi un format signé ? short block_align; short bits_per_sample; // !!! pourquoi un format signé ? char data_tag[4]; int data_length; // !!! pourquoi un format signé ? }; FILE * wavfile_open( const char *filename ) { struct wavfile_header header; int samples_per_second = SAMPLES_PER_SECOND; // int bits_per_sample = 16; int bits_per_sample = 8; strncpy(header.riff_tag, "RIFF", 4); strncpy(header.wave_tag, "WAVE", 4); strncpy(header.fmt_tag, "fmt ", 4); strncpy(header.data_tag, "data", 4); header.data_length = 0; header.fmt_length = 16; // !!! Pas 8 ? header.riff_length = 0; header.audio_format = 1; header.num_channels = 1; // !!! Un seul canal et NUM_SAMPLES doublé ? header.sample_rate = SAMPLES_PER_SECOND; header.byte_rate = SAMPLES_PER_SECOND * bits_per_sample / 8; header.block_align = bits_per_sample / 8; header.bits_per_sample = bits_per_sample; FILE * file = fopen(filename, "wb+"); if(!file) return 0; fwrite(&header, sizeof(header), 1, file); fflush(file); return file; } void wavfile_write( FILE *file, short data[], int length ) { fwrite(data, sizeof(short), length, file); // !!! C'est quoi l'intérêt ? } void wavfile_close( FILE *file ) { int file_length = ftell(file); int data_length = file_length - sizeof(struct wavfile_header); fseek(file, sizeof(struct wavfile_header) - sizeof(int), SEEK_SET); fwrite(&data_length, sizeof(data_length), 1, file); int riff_length = file_length - 8; fseek(file, 4, SEEK_SET); fwrite(&riff_length, sizeof(riff_length), 1, file); fclose(file); } int main() { //int volume = 32000; // En 16 bits int volume = 127; // !!! En 8 bits int length = NUM_SAMPLES; // !!! Toujours même problème de taille double frequency = 441.0; // !!! Pour que cela divise 44100 (saut de phase) double alpha = 0.0, delta = frequency * 2 * M_PI / SAMPLES_PER_SECOND; //short waveform[NUM_SAMPLES]; // En 16 bits signed char waveform[NUM_SAMPLES]; // !!! En 8 bits for(int i = length; i > 0 ; --i) { waveform[i] = round(volume*sin(alpha)); alpha =+ delta; // !!! Si maintes périodes prévoir un modulo 2PI } FILE * f = wavfile_open("essai_onefile.wav"); if(!f) { printf("couldn't open essai_onefile.wav for writing: %s", strerror(errno)); return 1; } // wavfile_write(f, waveform, length); // En 16 bits write(waveform, sizeof(signed char), length, f); // !!! En 8 bits wavfile_close(f); return 0; }
Salutations
Yep !
Et voilà mes réponses, peut-être fausses ou incomplètes, les spécialistes corrigeront :
ligne 18 const int NUM_SAMPLES = SAMPLES_PER_SECOND * 2; // !!! Stéréo ? Entrelacé ?
Les bytes se suivent à la queue leu leu, organisés suivant ce schéma (qu'on trouve un peu partout sur le web), selon que c'est stéréo ou mono :
Ça vient de là : http://soundfile.sapp.org/doc/WaveFormat/
les lignes 22, 25, 27, 28, 29, 31, 33 Voir avec l'auteur du tuto.
ligne 46 !!! Pas 8 ? Non, c'est le standard d'un fichier WAVE
ligne 49 !!! Un seul canal et NUM_SAMPLES doublé ? --> Je me suis posé la question et chez moi j'ai enlevé le * 2 de la ligne 18 pour Mono
ligne 63 : pas la moindre idée, ce qui amène une question : l'intérêt de quoi ?
ligne 80 : suit la ligne 18
lignes 84 et 95 : j'ai écrit unsigned car c'est la norme en 8 bits
+++
En ce qui me concerne, je ne peux pas comparer l'amplitude des ondes (heureusement les 44 premiers bytes sont strictement identiques, c'est déjà ça -- et c'est une confirmation pour Guesset : Audacity et ce code produisent le même code "technique") pour la bonne et simple raison que les deux logiciels n'ont pas la même échelle de valeur : Audacity va de -1 à +1 quand mon outil va de 0 à 126 unités de volume, ce qui impacte toute la zone de data.
Faudrait faire une règle de 3, qui va sans doute ajouter de l'imprécision, non ?
Bonjour,
Je ne vois pas pourquoi ne pas utiliser des signés pour y mettre des valeurs signées. D'autant que le comportement n'est pas le même en 16 bit (short est signé).
Une fonction qui se contente d'appeler une autre fonction me laisse sceptique. Quand, en plus, elle fait un présupposé de type 16 bits alors qu'on veut aussi travailler en 8 bits, elle m'apparaît plus comme un handicap qu'autre chose.
Mais ce n'est que mon avis
Salutations
Ah, ce n'est pas moi qui ai écrit ces spécifications.
Àmha, elles sont ainsi depuis le début du format wave, soit environ 30 ans...
Et c'est bien pour ça que nos codes sont pleins de...
Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part if untest then ceci else cela
Tiens, je me suis amusé à comparer un fichier mono en haut et le même en stéréo dessous, les deux étant en 8 bits unsigned et ayant été générés par Audacity.
Je montre les données différentes
et dessous les params communs aux deux fichiers :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 File : audac3secmono8bits.wav Channels : 1 Byte rate (bytes/s) : 44100 Block align : 1 Size of data block (bytes) : 132300 Total number of samples : 132300 File : audac3secstereo8bits.wav Channels : 2 Byte rate (bytes/s) : 88200 Block align : 2 Size of data block (bytes) : 264600 Total number of samples : 264600
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 SubChunkSize : 16 Audio format : $0001 (1 = PCM, uncompressed) SampleRate (samples/s) : 44100 Bits per sample : 8 Number of samples per channel : 132300 Duration (s) : 3.0
Je refais la manip avec du 16 bits signed, pour voir :
et ensuite les params communs, que je n'ai pas reproduits car identiques aux fichiers 8 bits sauf bien sûr le param Bits per sample : 16.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 File : audac3secmono16bits.wav Channels : 1 Byte rate (bytes/s) : 88200 Block align : 2 Size of data block (bytes) : 264600 Total number of samples : 132300 File : audac3secstereo16bits.wav Channels : 2 Byte rate (bytes/s) : 176400 Block align : 4 Size of data block (bytes) : 529200 Total number of samples : 264600
La taille des fichiers :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 8bits mono 129 kBytes 8bits stéréo 258 kBytes 16bits mono 258 kBytes 16bits stéréo 516 kBytes
Bonjour,
Si en 8 bit c'est un non signé qui est utilisé, cela ne suffit pas, il faut savoir la règle appliquée car il y a plusieurs façons d'avoir un résultat entre 0 et 255, entres autres (volume = 127):
Le dernier aurait ma préférence mais la norme en a peu être décidé autrement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 waveform[i] = round(127 + volume*sin(alpha)); // va de 0 à 254 => une position perdue, f(0) = 127 waveform[i] = round(128 + volume*sin(alpha)); // va de 1 à 255 => une position perdue, f(0) = 128 waveform[i] = round(127.5 + (volume+0.5)*sin(alpha)); // va de 0 à 255 => pas de position perdue, f(0) = 128 ...
Salutations
Bonsoir,
EDIT
j'ai fait le test suivant (3 essais) et j'ai mis les résultats en commentaire en haut :
Je ne sais pas quoi penser, il faudrait tester de 0 à 360 ° mais je n'ai pas le temps, là. Ni demain...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 a,b,alpha: integer; volume: double; begin alpha := 217; // 180 -> 128 127 --- 360 -> 128 128 --- 217 -> 128 127 a := round(128 + volume*sin(alpha)); // va de 1 à 255 => une position perdue, f(0) = 128 b := round(127.5 + (volume+0.5)*sin(alpha)); // va de 0 à 255 => pas de position perdue, f(0) = 128 memo1.lines.add(inttostr(a)+' '+inttostr(b));
Voir mon post suivant.
/EDIT
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager