GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 09-Jun-2006, 04:51
qrio12 qrio12 is offline
New Member
 
Join Date: May 2006
Posts: 7
qrio12 is on a distinguished road

Converting a BYTE array to a string


I am trying to read a wave file. However, in the code, it reads the RIFF header into a BYTE array using fread. It then compares the first 4 bytes, which should be "RIFF" if it is a wave file and continues if it is correct.

However, it uses strcmp, and that will not work with a BYTE array as an argument, is it possible to cast this to a string? The code I'm using is below, it is mostly taken from a tutorial found http://www.cpp-home.com/tutorial.php?333_1

CPP / C++ / C Code:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <windows.h>
#include <windef.h>
using namespace std;

void Load_Wave_File()
{
    FILE *fp;
	fp = fopen("D:\test1.wav","rb");
    if (fp)
    {
        BYTE id[4], *sound_buffer; //four bytes to hold 'RIFF'
        DWORD * size; //32 bit value to hold file size
        short format_tag, channels, block_align, bits_per_sample; //our 16 values
        DWORD format_length, sample_rate, avg_bytes_sec, data_size, i; //our 32 bit values
        fread(id, sizeof(BYTE), 4, fp); //read in first four bytes
        if (!strcmp(id, "RIFF"))
        { //we had 'RIFF' let's continue
            fread(size, sizeof(DWORD), 1, fp); //read in 32bit size value
            fread(id, sizeof(BYTE), 4, fp); //read in 4 byte string now
            if (!strcmp(id,"WAVE"))
            { //this is probably a wave file since it contained "WAVE"
                fread(id, sizeof(BYTE), 4, fp); //read in 4 bytes "fmt ";
                fread(&format_length, sizeof(DWORD),1,fp);
                fread(&format_tag, sizeof(short), 1, fp);
                fread(&channels, sizeof(short),1,fp); //1 mono, 2 stereo
                fread(&sample_rate, sizeof(DWORD), 1, fp); //like 44100, 22050, etc...
                fread(&avg_bytes_sec, sizeof(short), 1, fp); //probably won't need this
                fread(&block_align, sizeof(short), 1, fp); //probably won't need this
                fread(&bits_per_sample, sizeof(short), 1, fp); //8 bit or 16 bit file?
                fread(id, sizeof(BYTE), 4, fp); //read in 'data'
                fread(&data_size, sizeof(DWORD), 1, fp); //how many bytes of sound data we have
                sound_buffer = (BYTE *) malloc (sizeof(BYTE) * data_size); //set aside sound buffer space
                fread(sound_buffer, sizeof(BYTE), data_size, fp); //read in our whole sound data chunk
            }
            else
                printf("Error: RIFF file but not a wave file\n");
        }
        else
            printf("Error: not a RIFF file\n");
    }
}

I'm using Visual Studio 2003, and the errors I get in compilation are:
source.cpp(19): error C2664: 'strcmp' : cannot convert parameter 1 from 'BYTE [4]' to 'const char *'
and the same for the strcmp on line 23, a similar scenario

If you can give me any other helpful info, it would be appreciated too.
  #2  
Old 09-Jun-2006, 08:41
MichaelS-R MichaelS-R is offline
Junior Member
 
Join Date: Apr 2006
Location: Berkshire, UK
Posts: 65
MichaelS-R is on a distinguished road

Re: Converting a BYTE array to a string


There are a number of options as I see it. The simplest of which is to typecast the pointer to the BYTE array for the comparison (char *)id Is it always null terminated though? You assume that when you use strcmp. You probably want to use strncmp which allows you to specify the number of characters.

Hope this helps (and works!).

Michael.
__________________
Michael

Dual Opteron 280 (2 x dual core) with 2Gb RAM, 2x36GB system drives, 2T on 3Ware 9500Mi RAID controller. Running Fedora Core 4. Using Anjuta IDE. Developemnt in C++ with MySQL (via mysql++).
  #3  
Old 09-Jun-2006, 09:57
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,791
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Converting a BYTE array to a string


Quote:
Originally Posted by MichaelS-R
typecast the pointer to the BYTE array for the comparison (char *)id
Not effective since the array only holds four chars and, therefore doesn't have room for the terminating zero byte. You could declare the array to have five chars, read four chars from the file and set the fifth to zero, then use strcmp()

However...

Quote:
Originally Posted by MichaelS-R
You probably want to use strncmp which allows you to specify the number of characters.

Absolutely! That's the ticket.

Regards,

Dave
  #4  
Old 09-Jun-2006, 12:02
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,791
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Converting a BYTE array to a string


Quote:
Originally Posted by qrio12
I'm using Visual Studio 2003, and the errors I get in compilation are:
source.cpp(19): error C2664: 'strcmp' : cannot convert parameter 1 from 'BYTE [4]' to 'const char *'

According to a private communication I received, my previous post wasn't very clear. Sorry. I'll try again:

BYTE is typedef'ed in as an unsigned char and C++ is very picky about matching argument types to function parameters.

As MichaelS-R said, you could cast id (and, probably soundbuffer also) to (char *) at points where they are used. Or you could just declare them with char rather than BYTE (to make the C++ compiler happy).

Anyhow, after getting the data types correct, the program will compile, but please see the previous notes about why strcmp is ***not*** valid with the program as written (with strcmp using the string literal "RIFF" and a 4-byte array). It won't give compile errors, but will result in undefined behavior at run time: might give the right answer; might give the wrong answer; might do something completely different (including bomb).

The tutorial is just flat wrong in this respect.

The narrative seems OK to me, and the intent of the code is clear enough, but I have to wonder why someone would go to the trouble of posting a tutorial with a complete routine of C code and then say, "there's probably a few errors in this code as I didn't have time to compile and test it."

Regards,

Dave
  #5  
Old 09-Jun-2006, 23:53
qrio12 qrio12 is offline
New Member
 
Join Date: May 2006
Posts: 7
qrio12 is on a distinguished road

Re: Converting a BYTE array to a string


Thanks for the replies in this thread. I have done as suggested, and cast the BYTE array as a char pointer. It now compiles fine. I had to make another change due to a run time error, which said that the variable size was used without being declared.

However, my code still will not read a wave file. The thing just crashes if it's a wave file. Here's my code below:

CPP / C++ / C Code:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <windows.h>
#include <windef.h>
using namespace std;

void main()
{
    FILE *fp;
	fp = fopen("D:\\test1.wav","rb");
    if (fp)
    {
        BYTE id[4], *sound_buffer; //four bytes to hold 'RIFF'
        DWORD size; //32 bit value to hold file size
		DWORD * pSize = &size;
        short format_tag, channels, block_align, bits_per_sample; //our 16 values
        DWORD format_length, sample_rate, avg_bytes_sec, data_size, i; //our 32 bit values
        fread(id, sizeof(BYTE), 4, fp); //read in first four bytes
        if (strncmp((char *)id, "RIFF", 4) == 0)
        { //we had 'RIFF' let's continue
            fread(pSize, sizeof(DWORD), 1, fp); //read in 32bit size value
            fread(id, sizeof(BYTE), 4, fp); //read in 4 byte string now
            if (strncmp((char *)id,"WAVE", 4) == 0)
            { //this is probably a wave file since it contained "WAVE"
				printf("It knows its a wav file");
                fread(id, sizeof(BYTE), 4, fp); //read in 4 bytes "fmt ";
                fread(&format_length, sizeof(DWORD),1,fp);
                fread(&format_tag, sizeof(short), 1, fp);
                fread(&channels, sizeof(short),1,fp); //1 mono, 2 stereo
                fread(&sample_rate, sizeof(DWORD), 1, fp); //like 44100, 22050, etc...
                fread(&avg_bytes_sec, sizeof(short), 1, fp); //probably won't need this
                fread(&block_align, sizeof(short), 1, fp); //probably won't need this
                fread(&bits_per_sample, sizeof(short), 1, fp); //8 bit or 16 bit file?
                fread(id, sizeof(BYTE), 4, fp); //read in 'data'
                fread(&data_size, sizeof(DWORD), 1, fp); //how many bytes of sound data we have
                sound_buffer = (BYTE *) malloc (sizeof(BYTE) * data_size); //set aside sound buffer space
                fread(sound_buffer, sizeof(BYTE), data_size, fp); //read in our whole sound data chunk
				printf("Wav file read successfully");
            }
            else
                printf("Error: RIFF file but not a wave file\n");
        }
        else
            printf("Error: not a RIFF file\n");
    }
	else
		printf("WTF?");
}
Have I solved the 'size' variable being used without declared error correctly?

As I mentioned, the thing crashes if it's a wave file. Through some random comments put into the code, I know that the line:

CPP / C++ / C Code:
fread(sound_buffer, sizeof(BYTE), data_size, fp); //read in our whole sound data chunk

is causing the crash (as it won't happen if it's commented out). However, is it a problem with this line? Or the line above relating to creating a soundbuffer?
  #6  
Old 10-Jun-2006, 10:42
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,791
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Converting a BYTE array to a string


Quote:
Originally Posted by qrio12

However, my code still will not read a wave file.

I pointed out that there was at least one bug in the link that you furnished, and another statement that, "there's probably a few errors in this code as I didn't have time to compile and test it."

SO:

1. You know the program had a bug
2. The author admitted that he had not even compiled, much less, tested it.

I was hoping that you would find other sources to verify what the heck your program is supposed to do (and it is your program now that you have entered and compiled the code with your computer).
Bottom line: never use a single source for investigating. Look at other links.

You could go to msdn.microsoft.com and enter ".wav file format" into the search engine there, or you could go to other sites, for example: http://ccrma.stanford.edu/courses/42...ts/WaveFormat/

If you look carefully, you will see that the item avg_bytes_sec should be read in as a 32-bit quantity (DWORD), not a short. This throws off other things below it. (It is declared as a DWORD, but only two bytes are read from the file.)

Furthermore, the format given in your link only works for pcm files (where the format_tag has a value of 1). If you are working with any other format (adpcm or other kinds of compression) it simply won't work. It might read the first few headers OK, but you will then have to deal with some way of decompressing the actual sound data.

Now, whether either or both of these have anything to do with your problem, I don't know, but both should be checked. Please, please (please) don't take my word for it. Check other resources on the web.

I respectfully suggest that you study the information in the link that I gave, and when doing something new like this (reading a binary file with a particular format) that you print out exactly everything you read in from the file.

I have made a couple of minor changes, but not to the actual reading part of your program Here's what I tried:

CPP / C++ / C Code:
void print4char(BYTE *);

int main()
{
    BYTE id[4], *sound_buffer;
    DWORD size;
    short format_tag, channels, block_align, bits_per_sample;
    short extra_param_size;
    DWORD format_length, sample_rate, avg_bytes_sec, data_size, i;

    FILE *fp;
    /*char *filename = "start.wav"; */
    char *filename = "baloon.wav";
    fp = fopen(filename, "rb");

    
    if (fp) {
        printf("Opened %s for reading\n", filename);
        fread(id, sizeof(BYTE), 4, fp);
        printf("First 4 bytes (should be RIFF): ");
        print4char(id);
        if (strncmp((char *) id, "RIFF", 4) == 0) {

            fread(&size, sizeof(DWORD), 1, fp);
            printf("size            = %6d (0x%08x)\n", size, size);

            fread(id, sizeof(BYTE), 4, fp);
            printf("Next  4 bytes (should be WAVE): ");

            print4char(id);
            if (strncmp((char *) id, "WAVE", 4) == 0) {
                printf("---It knows its a wav file---\n");

                fread(id, sizeof(BYTE), 4, fp);
                printf("Next  4 bytes (should be fmt ): ");
                print4char(id);

                fread(&format_length, sizeof(DWORD), 1, fp);
                printf("format_length   = %6d (0x%08x)\n", 
                        format_length, format_length);

                fread(&format_tag, sizeof(short), 1, fp);
                printf("format_tag      = %6d (0x%04x)\n", 
                        format_tag, format_tag);
                fread(&channels, sizeof(short), 1, fp);
                printf("channels        = %6d (0x%04x)\n", 
                        channels, channels);

                fread(&sample_rate, sizeof(DWORD), 1, fp);
                printf("sample_rate     = %6d (0x%08x)\n", 
                        sample_rate, sample_rate);

                fread(&avg_bytes_sec, sizeof(DWORD), 1, fp);
                /*fread(&avg_bytes_sec, sizeof(short), 1, fp); */
                printf("avg_bytes_sec   = %6d (0x%08x)\n", 
                        avg_bytes_sec, avg_bytes_sec);

                fread(&block_align, sizeof(short), 1, fp); 
                printf("block_align     = %6d (0x%04x)\n", 
                        block_align, block_align);

                fread(&bits_per_sample, sizeof(short), 1, fp);
                printf("bits_per_sample = %6d (0x%04x)\n", 
                        bits_per_sample, bits_per_sample);

                if (format_tag != 1) {
                    printf("Not PCM: fmt subchunk has extra bytes\n");
                    fread (&extra_param_size, sizeof(short), 1, fp);
                    printf("extra_param_size = %6d (0x%04x)\n", 
                            extra_param_size, extra_param_size);
                    printf("Will throw away %d bytes\n", extra_param_size);
                    for (i = 0; i < extra_param_size; i++) {
                        fread(id, 1, 1, fp);
                    }
                    /* You could try some stuff here to handle files
                     * that are not pcm, or you could just bail out,
                     * as I do
                     */
                    printf("etc\n");
                    return 0;
                }

                fread(id, sizeof(BYTE), 4, fp);
                printf("Next 4 bytes (should be data): ");
                print4char(id);

                fread(&data_size, sizeof(DWORD), 1, fp);
                printf("data_size = %6d (0x%08x)\n", 
                        data_size, data_size);

                sound_buffer = (BYTE *) malloc(sizeof(BYTE) * data_size);
                fread(sound_buffer, sizeof(BYTE), data_size, fp);
                printf("Wav file read successfully");
            }
            else
                printf("Error: RIFF file but not a wave file\n");
        }
        else
            printf("Error: not a RIFF file\n");
    }
    else {
        printf("Can't open file %s for reading.\n", filename);
    }

    return 0;
}

void print4char(BYTE *b)
{
    int i;
    for (i = 0; i < 4; i++) {
        if (isprint(b[i])) {
            printf("(%c) ", b[i]);
        }
        else {
            printf("0x%02x ", b[i]);
        }
    }
    printf("\n");
}


With a file named baloon.wav (from windows\media directory):
Code:
Opened baloon.wav for reading First 4 bytes (should be RIFF): (R) (I) (F) (F) size = 6392 (0x000018f8) Next 4 bytes (should be WAVE): (W) (A) (V) (E) ---It knows its a wav file--- Next 4 bytes (should be fmt ): (f) (m) (t) ( ) format_length = 16 (0x00000010) format_tag = 1 (0x0001) channels = 1 (0x0001) sample_rate = 22050 (0x00005622) avg_bytes_sec = 44100 (0x0000ac44) block_align = 2 (0x0002) bits_per_sample = 16 (0x0010) Next 4 bytes (should be data): (d) (a) (t) (a) data_size = 6356 (0x000018d4)

With another file, start.wav from windows\media:

Code:
Opened start.wav for reading First 4 bytes (should be RIFF): (R) (I) (F) (F) size = 1184 (0x000004a0) Next 4 bytes (should be WAVE): (W) (A) (V) (E) ---It knows its a wav file--- Next 4 bytes (should be fmt ): (f) (m) (t) ( ) format_length = 50 (0x00000032) format_tag = 2 (0x0002) channels = 2 (0x0002) sample_rate = 22050 (0x00005622) avg_bytes_sec = 22311 (0x00005727) block_align = 1024 (0x0400) bits_per_sample = 4 (0x0004) Not PCM: fmt subchunk has extra bytes extra_param_size = 32 (0x0020) Will throw away 32 bytes etc

Regards,

Dave
 
 

Recent GIDBlogDeveloping GUIs with wxPython (Part 4) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help deleting the last element in the array headphone69 C++ Forum 2 15-Mar-2006 20:31
[c++] byte manipulation in a hex string czk101 C++ Forum 3 12-Feb-2006 11:12
Help wit my source code compiler errors Krandygrl00 C++ Forum 1 06-Jun-2005 09:14
Converting string to float CT++ C++ Forum 2 10-May-2005 12:29
template comiling problems - need expert debugger! crq C++ Forum 1 01-Feb-2005 22:26

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 17:23.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.