You are here:

C++/read wav file and write its HEX values into a file

Advertisement


Question
Yes, I'd like to write a program to read a wav file (the audio file) then output into 2 files the header and the data. The data file, I want its data in '1' and '0' so I can manipulate the data (analog pulses etc.) My question now is when output, what will seperate the header chunk from the data chunk.
Could you write the program with a little more details (more hints) since opening audio file, seperate it and convert to binary are very new to me (I am a hardware guy)

Thank you,

Tim
-------------------------

Followup To

Question -
Hi there,

I am a beginer with Visual C++. I'd like to write a script in Visual C++ to read a small (10 seconds or so) file and to seperate its chunks into a header file and data file (data file could be an array where stores hex value or binary value).  
Basicly, I want to the data value in HEX or binary.
HELP me...thanks

Tim

Answer -
First let us sort out some terms.

A script is usually a term reserved for something that automates a process. They are often written using interpreted languages that have specific features to aid in the process of automating processes for the environment they target. Examples are Windows CMD shell cmd and bat files, UN*X shell scripts, Perl scripts, various forms of Visual Basic for Applications.

However, when writing code using C++ we usually use the term program or application.

A script in Visual C++ is something that automates tasks using the environment. Examples might include setting up projects in a particular way for development of a large application, or code re-factoring.

I think you wish to write a program in C++, specifically Visual C++, to open a file encoded in MS WAV format, dump the headers in one file and the data into another.

Now it is beyond the scope of this forum to go into the details of WAV file structure, so I shall assume you are familiar with it. If not then I suggest you search for information in the MSDN library, which if you do not have a local copy can be found online at http://msdn.microsoft.com/, specifically at http://msdn.microsoft.com/library/.

Now I am not sure what you mean when you talk about hex and binary. All data in a digital system is stored as some form of binary representation. Binary integer data can be viewed as binary by converting the bits into '0' and '1' characters, into hex by converting groups of 4 bits into the characters '0' to '9' and 'a' to 'f', or as any other number base by providing the relevant conversion. For an example see the Visual C++ runtime library _itoa function family, which takes an integer (in binary format) as input and returns a char* C-style string representation of that value. The final parameter is a radix value allowing the caller to specify the number base of the value they with the integer to be formatted as and can be a value between 2 and 36 inclusive. Popular radix values would be 10 (decimal), 16 (hexadecimal), 2 (binary) and 8 (octal).

I shall therefore assume you wish the data files to contain data in text format, containing character representations of the WAV file data values as strings of hexadecimal digits.

In C++ you use the IOStreams library to handle files. Specifically std::fstream (file stream) and its variants std::ifstream (input file stream) and std::ofstream (output file stream). You include the header <fstream> in your code.

You need to open one input file and two output files (possible two per chunk - you do not say whether each chunk gets a header and data file or there is one header file and one data file for all chunks). You need to open the input file as binary to prevent end of line translation. As the data file is assumed to be a text file this file need not be opened in binary mode and can use the default mode of text. You give few details of what you wish to do with the header data so I shall not go into great detail for these files.

You can open a file for use with a std::fstream by using either a constructor or calling the open member. I shall use the constructor method here. You pass to the pathname and optionally a set of mode flags to indicate how the file should be opened. The default open mode flags differ for std::ifstream and std::ofstream to specify default open modes for reading and writing respectfully. The std::fstream class has no default open mode flags.

       std::fstream wavFile( "clip.wav", std::ios::in
         | std::ios::binary
         );

       if (wavFile.is_open() )
       {
       // continue...
       }

We can open the output files using the std::ofstream default open mode:

       std::ofstream dataFile( "clipData.txt" );

       if (dataFile.is_open() )
       {
       // continue...
       }

You will of course need to position the input file to the start of each chunk. You can do this using the seekg member function, for example:

     wavFile.seekg( chunkOffsetFromFileStart );

A second overload of the seekg member function takes a second parameter that allows you to specify to what the offset argument is relative to: the file start (std::ios::beg), the file end (std::ios::end) or the current position (std::ios::cur), for example:

     wavFile.seekg( chunkOffsetFromFileStart, std::ios::beg );

You can then write out the header data to the chunk header file and the chunk data to the chunk data file. As you are asking about the latter I shall focus on that. The idea is to simply read in bytes as chars from the wavFile input stream and write them out formatted appropriately as text to the dataFile stream. For this we can use a loop iterating for the number of bytes in the data portion of the chunk. Inside this loop we read a char from the input wavFile stream and output it to the dataFile stream:

   int aByte( wavFile.get() ); // aByte may also be EOF value

   // check wavFile  stream state for failures, fatal errors
   // and most specifically end of file

   dataFile << aByte << ' ';

   // check dataFile stream state for failures, fatal errors etc.

This writes data as one long line with each byte value separated by a space. I shall leave it to you to arrange the values as you wish. The main problem with it is that the values will be written as decimal values not hexadecimal values.

To change the format of the numbers written to the dataFile stream we use format flags to specify we wish numbers converted to hexadecimal format:

   dataFile.setf( std::ios::hex, std::ios::basefield );

Alternatively we can use manipulators inline with the << operator when writing the aByte values to dataFile:

   dataFile << std::ios::hex << aByte;

You should ensure header <ios> is included in your code to use the formatting flags and manipulators.

I should point out that if you try using a char in place of an int then you will get the character representing that value in the current character set, which for VC++ would, for example, have the byte 01000100 be written as "D" to dataFile and not "44" (the quotes are not written).

You can close file stream explicitly using their close member function or by destroying them. In these examples this would occur when they go out of scope as the stream objects are all local stack objects in the current call context. Note that if you wish to open another file using an existing file stream object that already has a file open on it you must close the current file first.

Hope this is of use. For more details on the C++ IOStreams library I would recommend a good C++ standard library reference such as "The C++ Standard Library A Tutorial and Reference" by Nicolai M. Josuttis which covers the whole C++ standard library and not just the IOStream portion of it. If you need more detail then consider "Standard C++ IOStreams and Locales" by Langer and Kreft. There is some online information at http://www.cplusplus.com/, specifically for IOStreams at http://www.cplusplus.com/ref/#libs and at http://www.digilife.be/quickreferences/PT.htm (which may have popups - you have been warned!).

Finally have you considered just opening the WAV file in a hex editor? OK you do not get the chunk header and data split out but the effort would be less, especially if this is a one off.

Anyhow hope this is of some use. Please ask follow up questions if you require further assistance.  

Answer
If you are asking how do you know where in the input file the header and data parts are then as I said before please refer to a description of the WAV file format as this sort of domain specific detail is beyond the scope of this forum (and my to-hand in-my-head knowledge!). I found a description here, among others:

   http://www.borg.com/~jglatt/tech/wave.htm

by typing:

   wav file format

into the Google search box - this proved easier than trying to locate the information in the MSDN library - however you might like to try searches of MSDN using RIFF in the query.

If you are not asking this then please could you explain further what it is that you are asking as I seem to have missed the point - in which case my apologies.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.