Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2006
    Messaggi
    24

    [C/C++] Problema con tipi double

    Ciao a tutti,
    sono un pò di giorni che ormai sbatto la testa per fare una cosa che inizialmente mi sembrava abbastanza semplice, e cioè estrarre la sezione raw-data da un file wav in formato double per poi elaborare il file così ottenuto successivamente. In pratica fare, in ambiente c/c++, quello che banalmente fa il comando wavread di matlab.
    Premetto che sono un novellino con c/c++, tuttavia guardando in internet ho trovato un piccolo codice che sembrava fosse adatto per i miei scopi. Il problema è dovuto al fatto che i dati estratti (per quanto io mi sia sforzato di fare dei casting a double) sono sempre restituiti in singola precisione (float). Di seguito allego il codice in questione e una parte dell'output con la speranza che possiate aiutarmi... le ho provate davvero tutte!
    Grazie in anticipo

    ------------------------------------BEGIN-----------------------------------------------
    // parser.cpp : definisce il punto di ingresso dell'applicazione console.
    //

    #include "stdafx.h"
    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    #include <iostream>
    #include <limits>
    #include <cfloat>
    #include <iostream>
    #include <iomanip>


    using namespace std;


    #include "parser.h"

    int _tmain(int argc, _TCHAR* argv[])
    {
    binaryToAscii();
    return 0;
    }

    void binaryToAscii()
    {
    FILE *infile, *outfile;
    char prefix[4];
    char fileFormat[8];
    unsigned char ch;
    double byteValue;
    unsigned int i;
    char ckID[5];
    unsigned long nChunkSize;
    short int wFormatTag;
    short int nChannels;
    unsigned long nSamplesPerSecond;
    unsigned long nAvgBytesPerSecond;
    short int nBlockAlign;
    short int nBitsPerSample;

    /* Open source for binary read (will fail if file does not exist) */
    infile = fopen( "C:\\temp\\parser files\\file1.wav", "rb" );
    {
    if (infile==NULL)
    //printf( "The source file %s was not opened!\n");
    exit(2);
    }

    /* Open output for write */
    outfile = fopen("C:\\temp\\parser files\\file1.txt", "w" );
    {
    if (outfile==NULL)
    //printf( "The output file %s was not opened\n");
    exit(3);
    }

    // Read the header bytes.
    fscanf( infile, "%4c", prefix );
    fscanf( infile, "%4c", &nChunkSize );
    fscanf( infile, "%8c", fileFormat );
    fscanf( infile, "%4c", &nChunkSize );
    fscanf( infile, "%2c", &wFormatTag );
    fscanf( infile, "%2c", &nChannels );
    fscanf( infile, "%4c", &nSamplesPerSecond );
    fscanf( infile, "%4c", &nAvgBytesPerSecond );
    fscanf( infile, "%2c", &nBlockAlign );
    fscanf( infile, "%2c", &nBitsPerSample );
    fscanf( infile, "%4s", &ckID );
    fscanf( infile, "%4c", &nChunkSize );

    // Testing on the file format variables would go here.

    // Scan and convert the bytes.
    for( i = 0; (i < nChunkSize);i++ ) {
    fscanf( infile, "%c", &ch );
    byteValue = ((double)ch-128)/128;
    fprintf_s(outfile,"%1.16lf\n",byteValue);
    }

    /* All files are closed: */
    fclose(infile);
    fclose(outfile);
    }

    ------------------------------------END-----------------------------------------------

    OUTPUT RESTITUITO
    -0.7031250000000000
    -1.0000000000000000
    -0.7812500000000000
    -1.0000000000000000
    -0.8906250000000000
    -1.0000000000000000
    0.9843750000000000
    0.9921875000000000
    0.8593750000000000
    0.9921875000000000
    0.8906250000000000
    0.9921875000000000
    0.9843750000000000
    0.9921875000000000
    -0.9531250000000000
    -1.0000000000000000
    -0.9843750000000000
    -1.0000000000000000
    -0.9531250000000000
    -1.0000000000000000
    -0.8906250000000000
    -1.0000000000000000
    -0.8906250000000000
    -1.0000000000000000
    -0.8750000000000000
    -1.0000000000000000
    -0.8281250000000000
    -1.0000000000000000
    -0.7968750000000000

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Questa parte di codice

    codice:
    // Scan and convert the bytes. 
    for( i = 0; (i < nChunkSize);i++ ) {
      fscanf( infile, "%c", &ch );
      byteValue = ((double)ch-128)/128;
      fprintf_s(outfile,"%1.16lf\n",byteValue);
    }
    non ha senso, rispetto a quello che vuoi fare.

    Cosi' leggi "byte per byte" e, con quella formula, lo converti in double ... ma cosa c'entra?

    Un double, all'interno di file, e' fatto da 8 byte ... devi leggere 8 byte per volta e utilizzarli per il tuo double ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2006
    Messaggi
    24
    La cosa che dici non mi torna.
    Io posso sempre fare una divisione tra due numeri rappresentati da un numero di byte inferiore a quelli usati per la rappresentazione di un double e poi ottenere il risultato della divisione con una rappresentazione a 8 byte. In sintesi, se prendo due numeri 1 e 3 rappresentati con un solo byte e dico che voglio il risultato della divisione rappresentato da un double otterrei:
    1/3=0.3333333333333333.
    Ed è quello che vorrei.

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Originariamente inviato da carminio
    se prendo due numeri 1 e 3 rappresentati con un solo byte e dico che voglio il risultato della divisione rappresentato da un double otterrei:
    1/3=0.3333333333333333.
    Questo vale per 1 diviso 3.

    Con quel ciclo stai effettuando tutte le operazioni comprese tra

    -128 / 128

    e

    127 / 128

    e ottieni i risultati double corretti con il numero di decimali necessari.

    Per capire meglio

    127 / 128 fa 0,9921875

    e il risultato e' questo senza altri decimali ...

    Per quanto riguarda la "logica" del programma inoltre, continuo a dirti che non ha senso leggere dei singoli byte (unsigned char) da un file in cui si pensa ci siano una serie di double ... ripeto, non devi leggere un singolo byte ma gli 8 byte dei vari double ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2006
    Messaggi
    24
    Ops! Hai perfettamente ragione Oregon! Mi concentravo sulla sintassi e non mi ero soffermato sui numeri, per cui quando vedevo dei risultati in singola precisione pensavo di aver sbagliato qualcosa.
    Per quel che riguarda la lettura del file va bene così, poichè nel file wav non ci sono dei double. La lettura va fatta byte per byte, è il risultato della normalizzazione che mi interessava avere in doppia precisione.
    Ti ringrazio tanto per avermi aiutato.
    Ciao.

  6. #6
    Utente di HTML.it
    Registrato dal
    Sep 2006
    Messaggi
    24
    Sempre a proposito del problema con il file wav...
    Dopo aver letto bene la descrizione della formattazione dei files wav, ho capito che nel mio caso il blocco di dati del wav è costituito da campioni con precisione a 2 byte, quindi a rigor di logica dovrei leggere 2 byte alla volta. Come posso fare? Ho provato con fscanf( infile, "%d", &ch1 ), con ch1 di tipo intero, oppure short, ma il risultato è stato disastroso...il file che scrivevo con questi valori letti, dopo la normalizzazione "(ch-128)/128" aveva tutti numeri uguali. Dove sbaglio?
    Insomma sto sbattendo la testa per leggere sto benedetto file wav da ormai troppi giorni, mi dite come posso fare? Ripeto che vorrei ottenere lo stesso risultato della funzione wavread di matlab e ormai mi sembra di essere vicino alla soluzione, ma evidentemente, sebbene ho isolato il blocco dati dal resto della struttura del wav, non leggo questi valori in modo corretto.
    Help me!

  7. #7
    Vuoi leggere due byte ?
    codice:
    typedef union _Word {
    
       short value;
    
       struct {
    
          char byte[2];
    
       }sBytes;
    
    }uWord;
    Così sei sicuro siano due byte.
    Poi usi fread (che è meglio visto che usi file binari ...):
    codice:
    uWord word;
    
    fread(&word.sBytes, sizeof(word.sBytes), 1, file_pointer);
    e accedi al valore, con:
    codice:
    printf("%d\n", word.value);
    e puoi accedere ai singoli byte, con:
    codice:
    printf("Byte1: %d, Byte2: %d\n", word.sBytes.byte[0], word.sBytes.byte[1]);

  8. #8
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Se non ti servono i singoli byte e ti serve un valore con il segno, puoi semplicemente usare

    codice:
    short int v;
    
    fread(&v, sizeof(v), 1, infile);
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  9. #9
    Utente di HTML.it
    Registrato dal
    Sep 2006
    Messaggi
    24
    OK! Problema risolto...finalmente. Grazie a tutti voi per i preziosi consigli. Ciao.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.