3

I am entirely new to C++ with just a couple of hours self-teaching, that started yesterday. SO:

I have a uncompressed simple beep.wav file, just about 3 seconds long with a single beeping sound in it.

What I am ultimately trying to achieve is, just to read the file, and at the same time write the binary data, all including: the header, ftm and data or all that is hex readable data and dump it into a simple beep.txt file.

is this possible, in C++? If so, how should I begin reading and dumping the binary file?

I can read the file ~more or less, using the <fstream> class

#include <iostream>
#include <fstream>

   int main()
   {
       ifstream myfile ("beep.wav", ios::in|ios::binary|ios::ate);
       if (myfile.is_open())
       {
        //reading goes here
        }
       return 0;
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
blue thief
  • 113
  • 3
  • 14
  • 1
    What are you trying to achieve? Why do you want to write binary data to a text file? What do you expect the text file will have that the binary data doesn't? – xxbbcc Jun 17 '13 at 00:58
  • 2
    First of all, functionality-wise, everything that computer can do is possible in C++ (as with most other general-purpose programming languages.) The world runs on C and C++, so it can be done. However, it's entirely *unclear* what you actually want to do. Do you want to copy a file's contents into another? Do you want to parse the WAV header and PCM data and convert them to text? Do you even know how a an uncompressed (aka PCM) WAV file is structured? – yzt Jun 17 '13 at 01:00
  • 1
    @xxbbcc Well, I am learning C++ to create a sound manipulation tool, and in-order to understand everything how it works from 0. I need to learn/experiment with how storage of binary data works, and how to manipulate it. – blue thief Jun 17 '13 at 01:01
  • @yzt Like above I said, I have been learning about sound, audio signals, and audio drivers this subject is my way up to understand how works.So, I am just trying to play with it.. if you will. – blue thief Jun 17 '13 at 01:02
  • @bluethief In that case you first need to learn the difference between binary files and text files. There's a reason these exist and one cannot directly write content from one into another without consequences. You can read the contents of a WAV file but to write it to a text file in a meaningful way, you'll have to translate the data. How to do that depends on what kind of text output you desire. – xxbbcc Jun 17 '13 at 01:09
  • @xxbbcc Thanks I like your advice very much. Once I just fiddle with this thing, I will create a simple spectrogram. And The application I want to build will be based on spectrograms. If you have an advice that will help me move further, I would love to hear it – blue thief Jun 17 '13 at 01:21

4 Answers4

3

As mentioned by yzt, you need to know by advance what's in your .wav and in which order. As far as I know, you will have tags, headers and values (samples) as well as compression informations. So, to give a start :

If you know, by example, that the very first thing to do is to read the compression rate, you'll start your reading process by extracting may be a double :

ifstream myfile("beep.wav", ios::in|ios::binary);

double compression_rate;
myfile.read((char*)&compression_rate, sizeof(compression_rate));

// As well as probably the sample rate...
double sample_rate;
myfile.read((char*)&sample_rate, sizeof(sample_rate));

Then, may be, the number of samples :

int nb_samples;
myfile.read((char*)&nb_samples, sizeof(nb_samples));

Then, the values for those samples... (here stored as a vector of double)

vector<double> vect;
vect.resize(nb_samples);
myfile.read((char*)&vect[0], nb_samples * sizeof(double));

Etc...

But again, what the .wav you opened is made of ?

Once you completely master the content, you can go the other way and start writing your own .wav from scratch...


Getting started - and here.

Bytes - "Autopsy" of a PCM Wav file.

Community
  • 1
  • 1
Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85
  • Well, thanks but I am kindf lost here, with these new functions. I can't say much about the type of `.wav` file either, because it is uncompressed simple audio-only wav file. – blue thief Jun 17 '13 at 01:27
  • Well, those are ways to read binarized data from an `ifstream`. While you read a value (let's say a `double`), you store it in a variable. As a result `compression_rate` gets is value AND the file cursor's position is shifted of the size of a `double`. Then, you are ready to read the next information (here the `int`). The cursor is moved again. Then you read, from the current position, `nb_samples` times a double (again, each time a value is read, the cursor is shifted)... until the reading is over (EOF). Does it make more sense to you ? – Gauthier Boaglio Jun 17 '13 at 01:37
  • Thanks. I have a better picture now than I did before. But the links were just amazing. – blue thief Jun 17 '13 at 09:28
  • Glad to help ! The second link requires that you get familiar (if it is not the case already) with the [size (in bytes) of C types](http://stackoverflow.com/q/589575/1715716). The `read` function simply reads a certain amount of bytes. This is the purpose of the second parameter this function takes, and this is as well the purpose of the `size` column of the table located at the middle of the web page. Good luck with your `sound manipulation tool` project... – Gauthier Boaglio Jun 17 '13 at 09:43
  • Thanks. I am learning as I go along. the sound manipulate tool is just a spectrogram. Just very simple one. I am learning these, just to be able to create one, hopefully within this week – blue thief Jun 17 '13 at 09:56
  • I would be very interested in seeing what it gives. If you can share something when you get results, that would be awesome. – Gauthier Boaglio Jun 17 '13 at 10:00
2

This example will read the data from the input file and write it as 2-character hex values (text).

ofstream outfile("beep.txt");
outfile << hex << setfill('0');

char c;
while( outfile.good() && myfile.get(c) )
{
    outfile << setw(2) << +(unsigned char)c;
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • thanks paddy, I tried to integrate your code, into mine as mentioned, however, I am getting errors.. more concisely `'ifsteam' was not declared in this scope` What does it mean? It was working fine, before adding you code.. weird.. – blue thief Jun 17 '13 at 01:30
  • 2
    Read the error message carefully... It's trying to tell you that there's no such thing as `ifsteam` (check your spelling). – paddy Jun 17 '13 at 01:39
  • 1
    @bluethief: It's apparent you need a good book that you can readily reference and/or get familiar with a [C++ Internet Reference](https://www.google.com/search?q=c%2B%2B+reference+sites&rlz=1C1CHFX_enUS468US468&oq=c%2B%2B+reference+sites&aqs=chrome.0.57j0j60l2j0.7410j0&sourceid=chrome&ie=UTF-8) that is more than just a Q&A forum. – ChiefTwoPencils Jun 17 '13 at 02:01
2

The WAV file format specification tells you the binary layout of WAV files - you need this because this tells you what bytes to read in what order. (You'll really need to read int-s and various other fields in addition to bytes.) Once you read this information, you can translate it for display and write it out to a text file. For example, you can write out the length (duration) of the sound in the WAV file by reading the header (I don't know the exact layout) and then calculate how many seconds that translates to.

In technical terms all other answers to your question are good - they give you pointers on how to read / write binary & text data in C++.

xxbbcc
  • 16,930
  • 5
  • 50
  • 83
1

You can read the entire file into a buffer:

  1. Seek to the end of the file
  2. Make a buffer big enough to fit the file
  3. Seek back to the start of the file
  4. Read the entire file into the buffer

:

myfile.seekg(0, std::ios::end);
std::string buffer(myfile.tellg(), '\0');
myfile.seekg(0);

myfile.read(&buffer.front(), buffer.size());
David
  • 27,652
  • 18
  • 89
  • 138