C++, char vers integer, binaire
Résolu/Fermé
A voir également:
- C++, char vers integer, binaire
- Codage binaire - Guide
- Windows 7 vers windows 10 - Accueil - Mise à jour
- Clavier qwerty vers azerty - Guide
- Transferer photo android vers pc - Guide
- Vers quelle adresse web renvoie ce lien - Guide
9 réponses
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
17 janv. 2009 à 21:59
17 janv. 2009 à 21:59
Salut,
Si c'est un seul caractère, une simple soustraction par le code ascii '0' marchera.
Par contre si tu veux plusieurs caractères, il y a la fonction atoi ou strtol qui pourrait sûrement t'aider. Elles récupéreront le plus gros nombre.
Cdlt
Si c'est un seul caractère, une simple soustraction par le code ascii '0' marchera.
Par contre si tu veux plusieurs caractères, il y a la fonction atoi ou strtol qui pourrait sûrement t'aider. Elles récupéreront le plus gros nombre.
int nb=atoi(chaine);
Cdlt
Bonjour
Quel langage de programmation utilises-tu ? Tous les langages ont une fonction pour transformer un caractère d'une chaîne en nombre et réciproquement.
Fais bien attention quand tu manipuleras ces nombres : quand tu les additionnes ou que tu les soustrais, tu vas avoir de dépassements de capacité.
Et du son en 8 bits... je ne sais pas ce que tu veux en faire, mais ça ne va pas être de la hifi !
Quel langage de programmation utilises-tu ? Tous les langages ont une fonction pour transformer un caractère d'une chaîne en nombre et réciproquement.
Fais bien attention quand tu manipuleras ces nombres : quand tu les additionnes ou que tu les soustrais, tu vas avoir de dépassements de capacité.
Et du son en 8 bits... je ne sais pas ce que tu veux en faire, mais ça ne va pas être de la hifi !
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
17 janv. 2009 à 22:04
17 janv. 2009 à 22:04
C'est écrit C++ dans le titre ;)
J'essaye de lire attentivement le message, j'oublie le titre...
Dans ce cas, il n'y a aucune sorte d'intérêt à mettre les données dans une chaine de caractères : un bon vieil array de signed char ou short est très très nettement préférable. Il n'y a aucune sorte de transcodage à faire par rapport aux données lues depuis un fichier wav. Toutes les opérations d'addition, soustraction se font naturellement (re-attention aux dépassements de capacité !).
Dans ce cas, il n'y a aucune sorte d'intérêt à mettre les données dans une chaine de caractères : un bon vieil array de signed char ou short est très très nettement préférable. Il n'y a aucune sorte de transcodage à faire par rapport aux données lues depuis un fichier wav. Toutes les opérations d'addition, soustraction se font naturellement (re-attention aux dépassements de capacité !).
Très bien, j'essaye tout ça rapidement demain.
En revanche, si je traites mes données en décimal (integer), et que je veux ensuite répasser ces valeurs en caractère (string), j'ai les fonctions inverses ? ( Itostr )
En revanche, si je traites mes données en décimal (integer), et que je veux ensuite répasser ces valeurs en caractère (string), j'ai les fonctions inverses ? ( Itostr )
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
17 janv. 2009 à 22:30
17 janv. 2009 à 22:30
Si tu l'as en décimal, et que tu veux le mettre en binaire, non pas de fonctions inverses. Tu devras te la coder, mais c'est pas dur ;) En revanche si tu veux mettre le nombre en décimal tu peux utiliser sprintf ou mieux snprintf.
snprintf(chaine,sizeof chaine,"%d",nb);
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Mahmah
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
125
18 janv. 2009 à 16:03
18 janv. 2009 à 16:03
Bonjour,
Selon moi, oui.
Un point devient flou au fur et à meusure des posts :
Prenons un échantillon 8 bit signé, donc entre -128 et 127 : Je pense que cet échantillon n'est pas écrit en texte dans ta chaîne de caractères mais bien en données binaires.
Une précision est nécessaire : L'échantillon de valeur 127 est-il écrit dans ta chaîne de caractère avec le caractère '1' puis le caractère '2' puis le '7', donc trois caractères et au format texte ou est-il codé sur un seul caractère dont la valeur est 127 ? (Comme dans un fichier .wav par exemple)
1) Format binaire :
Il n'existe pas de base un type numérique codé sur 8 bits (peut-être le short short int, je n'en suis même pas sûr) Il est donc courant d'utiliser le type char comme un nombre en lui retirant toute sa valeur de caractère.
L'usage de templates serait une très bonne idée
Le type char est souvent utilisé parce qu'il fait 8 bits, l'ordinateur ne fait pas de différence entre un nombre et le caractère qu'il représente. (c'est d'ailleurs pour cela que l'on a 'A' - 32 == 'a' et que l'ordi le comprend très bien)
2) Format texte
Si les échantillons sont au format texte, il manque une précision : admettons que j'ai la chaîne de caractères suivante "127127127", je peux très bien avoir entre 3 et 9 échantillons, comment le sait-on ?
Pour repasser du format numérique au format texte il y a sprintf.
Merci donc de préciser le format que tu as en entrée, binaire ou texte.
Si tes données sont en Big Endian et que ton ordinateur ne l'est pas, oui il faudra transformer.
M.
Colin, le samedi 17 janvier 2009 à 21:54:19 Un cast suffit-il ?
Selon moi, oui.
Un point devient flou au fur et à meusure des posts :
Prenons un échantillon 8 bit signé, donc entre -128 et 127 : Je pense que cet échantillon n'est pas écrit en texte dans ta chaîne de caractères mais bien en données binaires.
Une précision est nécessaire : L'échantillon de valeur 127 est-il écrit dans ta chaîne de caractère avec le caractère '1' puis le caractère '2' puis le '7', donc trois caractères et au format texte ou est-il codé sur un seul caractère dont la valeur est 127 ? (Comme dans un fichier .wav par exemple)
1) Format binaire :
Il n'existe pas de base un type numérique codé sur 8 bits (peut-être le short short int, je n'en suis même pas sûr) Il est donc courant d'utiliser le type char comme un nombre en lui retirant toute sa valeur de caractère.
// On simplifie en définissant deux formats
typedef signed char Sample8; // type 8 bits pour la définition du Sample8
typedef signed short Sample16; // type 16 bits pour la définition du Sample16
// (éventuellement, lorsque que le code sera compilé sur un ordinateur ayant des tailles différentes pour les types de base, seuls ces deux typedef seront à changer.)
// Les échantillons : (Au format binaire)
char *pData; // Je suppose qu'il sont dedans, je ne sais pas comment ils sont obtenus.
// 8 bits par échantillon
if ( bitsPerSample == 8 )
{
// variable locale et temporaire pour éviter de mettre des casts partout
Sample8 *pSamples = (Sample8 *) pData; // Je change l'interprétation des données
unsigned int numSamples = dataSize / sizeof( Sample8 );
// Traitement
...
pSamples[i] = ...;
...
}
// 16 bits par échantillon
else if ( bitsPerSample == 16 )
{
Sample16 *pSamples = (Sample16 *) pData;
unsigned int numSamples = dataSize / sizeof( Sample16 ); // 2 octets par échantillons
...
pSamples[i] = ...;
...
}
L'usage de templates serait une très bonne idée
Le type char est souvent utilisé parce qu'il fait 8 bits, l'ordinateur ne fait pas de différence entre un nombre et le caractère qu'il représente. (c'est d'ailleurs pour cela que l'on a 'A' - 32 == 'a' et que l'ordi le comprend très bien)
2) Format texte
Si les échantillons sont au format texte, il manque une précision : admettons que j'ai la chaîne de caractères suivante "127127127", je peux très bien avoir entre 3 et 9 échantillons, comment le sait-on ?
Pour repasser du format numérique au format texte il y a sprintf.
Merci donc de préciser le format que tu as en entrée, binaire ou texte.
Si tes données sont en Big Endian et que ton ordinateur ne l'est pas, oui il faudra transformer.
M.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 842
18 janv. 2009 à 16:33
18 janv. 2009 à 16:33
Un char ne fait pas forcément 8 bits bien que ce soit souvent le cas.
Bonjour Mahmah,
Le format est bien au format binaire, ton post est donc très interessant.
Je tente de reprendre le code : j'ai ma variable de taille adaptée pSamples[i], en gros 8 ou 16 bits, je veux l'attenuer et la remettre à sa place :
Et.. cela suffit-il ? Mon tableau original est-il modifié comme je le souhaite ?
Je manque un peu de fraicheur pour comprendre rapidement ce 18 janvier...
Le format est bien au format binaire, ton post est donc très interessant.
Je tente de reprendre le code : j'ai ma variable de taille adaptée pSamples[i], en gros 8 ou 16 bits, je veux l'attenuer et la remettre à sa place :
... // attenuation de la valeur pSamples[i] = (int)pSample[i]*0,5; ...
Et.. cela suffit-il ? Mon tableau original est-il modifié comme je le souhaite ?
Je manque un peu de fraicheur pour comprendre rapidement ce 18 janvier...
Mahmah
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
125
18 janv. 2009 à 17:27
18 janv. 2009 à 17:27
Oui, le passage en nombre flottant n'est forcément pas nécessaire.
// attenuation de la valeur
pSamples[i] = pSample[i] / 2;
Ou, si on souhaite appliquer un coefficient, on convertit effectivement en float
pSample[i] = (Sample16) ( (float) pSample[i] * 0.5f );
Il faut se méfier des opérations en nombres entiers tel que :
pSample[i] = pSample[i] * 1 / 2;
En nombre entier 1 / 2 vaut 0.
M.
// attenuation de la valeur
pSamples[i] = pSample[i] / 2;
Ou, si on souhaite appliquer un coefficient, on convertit effectivement en float
pSample[i] = (Sample16) ( (float) pSample[i] * 0.5f );
Il faut se méfier des opérations en nombres entiers tel que :
pSample[i] = pSample[i] * 1 / 2;
En nombre entier 1 / 2 vaut 0.
M.
Merci pour ces infos, ça avance, et c'est beaucoup plus simple comme ça !
Je ne fais que l'attenuation pour le moment : ça fonctionne avec pSamples[i] = pSample[i] / 2; , mais comme cela :
ça ne fonctionne pas, sortie muette, donc le resultat obtenu est nul.
Dans ta synthaxe tu met pSample[i] = (Sample16) ( (float) pSample[i] * 0.5f ); A quoi sert le f derrière 0.5 ?
Je ne fais que l'attenuation pour le moment : ça fonctionne avec pSamples[i] = pSample[i] / 2; , mais comme cela :
if ( projectFormat.wBitsPerSample == 16 ) { Sample16 *pSamples = (Sample16 *) WaveData; unsigned int numSamples = DataSize / 2; // 2 octets par échantillons for(unsigned int i=0; i<numSamples; i++) pSamples[i] = (Sample16)((float)pSamples[i]*ap); }
ça ne fonctionne pas, sortie muette, donc le resultat obtenu est nul.
Dans ta synthaxe tu met pSample[i] = (Sample16) ( (float) pSample[i] * 0.5f ); A quoi sert le f derrière 0.5 ?
Cela fonction sans problème en 16bits, cependant, en 8bits j'ai :
pour
typedef unsigned char Sample8; // type 8 bits for Sample8
un son atténué mais avec un petit bruit aigu ajouté
typedef signed char Sample8; // type 8 bits for Sample8
le son de base clairement reconaissable mais avec un gros bruit au dessus (parasites)
Si ce sont les caractèrs ANSI utilisés, quel doit etre le type utilisé dans le typedef ?
pour
typedef unsigned char Sample8; // type 8 bits for Sample8
un son atténué mais avec un petit bruit aigu ajouté
typedef signed char Sample8; // type 8 bits for Sample8
le son de base clairement reconaissable mais avec un gros bruit au dessus (parasites)
Si ce sont les caractèrs ANSI utilisés, quel doit etre le type utilisé dans le typedef ?
Mahmah
Messages postés
496
Date d'inscription
lundi 17 septembre 2007
Statut
Membre
Dernière intervention
22 juin 2010
125
18 janv. 2009 à 21:06
18 janv. 2009 à 21:06
Toi seul sais si les échantillons 8 bits qui te sont fournis sont signés ou non.
C'est la première chose a fixer.
Ensuite il faut essayer de voir ce qu'il se passe pour que le son soit déformé.
1) Sans toucher au son
2) En lisant puis ré-écrivant sans modifier les échantillons
3) En modifiant les échantillons
Pour voir quand les parasites arrivent. Si possible, les observer avec un logiciel audio.
Je vérifierais l'endianness en premier à ta place.
M.
ANSI se rapporte a des caractères, tes char ne sont que des nombres, pas de véritables caractères.
(Si j'ai bien compris jusque là)
C'est la première chose a fixer.
Ensuite il faut essayer de voir ce qu'il se passe pour que le son soit déformé.
1) Sans toucher au son
2) En lisant puis ré-écrivant sans modifier les échantillons
3) En modifiant les échantillons
Pour voir quand les parasites arrivent. Si possible, les observer avec un logiciel audio.
Je vérifierais l'endianness en premier à ta place.
M.
ANSI se rapporte a des caractères, tes char ne sont que des nombres, pas de véritables caractères.
(Si j'ai bien compris jusque là)
Ok, l'erreur vient du traitement en 8bits qui est non signé. L'attenuation se porte sur l'echelle 0 - 255 et non pas sur -127 - 127. Il faut donc que je traite le 8 bits specialement comme cela :
On calcule la valeur en soustrayant 127 et on la re-range en rajoutant les 17 (après traitement)
if ( projectFormat.wBitsPerSample == 8 ) { // local temporary variable to avoid cast everywhere Sample8 *pSamples = (Sample8 *) echoWaveData; // change data interpretation // Traitment // take care of 8 bits format for(unsigned int i=0; i<DataSize+dp; i++) pSamples[i] = (Sample8)((((int)pSamples[i]-127) * ap) + 127); }
On calcule la valeur en soustrayant 127 et on la re-range en rajoutant les 17 (après traitement)
C'est bon, j'ai trouvé ce qu'il me faut : voici la fonction qui ajoute de l'echo sur un son Wave stocké dans une chaîne de caractères :
projectFormat est un WAVEFORMATEX :
Merci pour votre aide, ça m'a bien servi !
projectFormat est un WAVEFORMATEX :
void Echo(float ap_float_user, int dp_bytes_user) { // parameter attenuation : "ap" // parameter delay : "dp" if(projectFormat.wBitsPerSample!=8 && projectFormat.wBitsPerSample!=16) { ShowMessage("Sorry, format not supported for echo effect"); return; } float ap; int dp; ap = ap_float_user; // atenuation parameter dp = dp_bytes_user * projectFormat.nChannels; // delay in bytes, multiple of 2 // this value has to be multiple of nbChannels, here 2 or 1 char* echoWaveData = new char[DataSize+dp]; char* effectWaveData = new char[DataSize+dp]; // copy WaveData into echoWaveData with decalage for(unsigned int i=0; i<DataSize+dp; i++) { if(i<(unsigned int)dp && projectFormat.wBitsPerSample == 8) echoWaveData[i]= (Sample8)128; // silent 128 else if(i<(unsigned int)dp && projectFormat.wBitsPerSample == 16) echoWaveData[i]=(Sample16)0; else echoWaveData[i]= WaveData[i-dp]; } // end of copy with decalage // OK 16bits, OK 8bits // attenuation of echoWaveData // 8 bits per sample if ( projectFormat.wBitsPerSample == 8 ) { // local temporary variable to avoid cast everywhere Sample8 *pSamples = (Sample8 *) echoWaveData; // change data interpretation // Traitment // take care of 8 bits format for(unsigned int i=0; i<DataSize+dp; i++) pSamples[i] = (Sample8)((((int)pSamples[i]-127) * ap) + 127); } // 16 bits per sample else if ( projectFormat.wBitsPerSample == 16 ) { Sample16 *pSamples = (Sample16 *) echoWaveData; unsigned int numSamples = (DataSize+dp) / 2; // 2 bytes per sample for(unsigned int i=0; i<numSamples; i++) pSamples[i] = (Sample16)((float)pSamples[i] * ap); } // end attenuation // OK 16bits, OK 8bits // addition of two signals if ( projectFormat.wBitsPerSample == 8 ) { // local variable to change interpretation Sample8 *pSamplesOri = (Sample8 *) WaveData; Sample8 *pSamplesEco = (Sample8 *) echoWaveData; Sample8 *pSamplesEffect = (Sample8 *) effectWaveData; // Traitement // have to treat case of sum > 127 // we will add wave divide by 2 // and multiply it by 2 at the end for(unsigned int i=0; i<DataSize+dp; i++) { // do not copy data from WaveDatz[DataSize_or_more] // no existing data here if(i>=DataSize) { pSamplesEffect[i] = (Sample8)((int)64 + (int)pSamplesEco[i]/2); // because we divide all by 2 } else { pSamplesEffect[i] = (Sample8)((int)pSamplesOri[i]/2 + (int)pSamplesEco[i]/2); } } // Now, amplification of signal by 1.5 // take care of 8 bits format for(unsigned int i=0; i<DataSize+dp; i++) pSamplesEffect[i] = (Sample8)((((int)pSamplesEffect[i]-127) * 1.4) + 127); } // 16 bits per sample else if ( projectFormat.wBitsPerSample == 16 ) { Sample16 *pSamplesOri = (Sample16 *) WaveData; Sample16 *pSamplesEco = (Sample16 *) echoWaveData; Sample16 *pSamplesEffect = (Sample16 *) effectWaveData; unsigned int numSamples = (DataSize+dp) / 2; // 2 octets par échantillons for(unsigned int i=0; i<numSamples; i++) { // do not copy data from WaveDatz[DataSize_or_more] // no existing data here if(i>=DataSize/2) pSamplesEffect[i] = (Sample16)((int)0 + (int)pSamplesEco[i]/2); else pSamplesEffect[i] = (Sample16)((int)pSamplesOri[i]/2 + (int)pSamplesEco[i]/2); } for(unsigned int i=0; i<numSamples; i++) pSamplesEffect[i] = (Sample16)((float)pSamplesEffect[i] * 1.4); } // end addition of two signals // 16 bits : OK // 8 bits : not at all, data more than +/-127 // copying result into WaveData if(WaveData) delete[] WaveData; WaveData = new char[DataSize+dp]; for(unsigned int i=0; i<DataSize+dp; i++) WaveData[i] = effectWaveData[i]; // end copying // destroying buffer delete[] echoWaveData; delete[] effectWaveData; // reconfigure DataSize DataSize = DataSize + dp; }
Merci pour votre aide, ça m'a bien servi !
17 janv. 2009 à 22:10
Je crois que ce n'est pas ce qu'il me faut, j'obtiendrais ainsi la valeur entière qui est écrite dans le char non ?
Je veux dire, si mon char est '8' mon int sera 8
char 8 bin: 00111000(56 en ascii) mais int: 8
Ce que je veux c'est
char 8 bin: 00111000(56 en ascii) et donc 56 en sortie
sur 16 bits c'est autre chose.
Je vais vérifier tu as peut être raison. Dans ce cas puis-je aussi utiliser atoI et strtoI avec une chaine de 1 caractère ?
17 janv. 2009 à 22:17
Par exemple : si ta chaine vaut "1001", renverra 9 et non 1001. Et ça prendra le plus long nombre possible, donc si ta chaîne fait "10000000000000001", ça marchera aussi. Tant que ça dépasse pas long du moins ^^.
Sinon pour une chaîne d'un caractère, oui ça marche. Mais pas sur un caractère simple. Pour le caractère simple, une simple soustraction.