endianness in written files seems to change

F

Fabian Lenzen

Hi,

I am currently working on a program that writes a RIFF wave file. The
big problem is writing the data chunk: Wikipedia told me that a wave
file has to be encoded in little endian, and I found out that my machine
also uses little endian, so simply copying the memory containing the
sample values to a file should be enough. This also seems to work.

My Code:

*********
typedef uint16_t sample_format;
class WaveStream{
public: // Only for testing purposes
char header[44];
sample_format* samples;
int size;
int index;
public:
WaveStream(int _size): size(_size){
samples = new sample_format[_size];
for(int i = 0; i < size; i++)
samples = 0;
index = 0;
}
void operator<<(sample_format i){
samples[index++] = i;
}
void write(ostream& out){
uint32_t filesize = size *
sizeof(sample_format) + 44 - 8;
uint32_t chunksize = 16;
uint16_t datasize = size * sizeof(sample_format);
uint16_t format = 0x0001;
uint16_t channels = 1;
uint32_t samplerate = 11025;
uint32_t bitsps = 16;
uint16_t blockalign = bitsps * channels / 8;
uint32_t bytesps = samplerate * blockalign;
out.write("RIFF", 4);
out.write((char*)&filesize, 4);
out.write("WAVE", 4);
out.write("fmt ", 4);
out.write((char*)&chunksize, 4);
out.write((char*)&format, 2);
out.write((char*)&channels, 2);
out.write((char*)&samplerate, 4);
out.write((char*)&bytesps, 4);
out.write((char*)&blockalign, 2);
out.write((char*)&bitsps, 2);
out.write("data", 4);
out.write((char*)&datasize, 4);
out.write((char*)samples, size * sizeof(sample_format));
}
};
*********

I write the data to the wave-file with the following code:


*********
ofstream file("test.wav");
WaveStream w(11025);
cout << hex;

for(int i = 0; i < 11025; i++){
sample_format s = (sample_format)(cos(((float)i)*2*M_PI/11025
* 220) * (1 << 6));

cout.width(4);
cout.fill('0');
w << s;
cout << w.samples << ' ';
}
w.write(file);
file.close();
*********

The Code writes the sample values to the samples[]-memory, and puts the
values stored in samples[] out so that I can control the output. But if
I compare the program's output on stdout and the file's content,
something strange happens (only the sample data section of the data
chunk is displayed, display in human readable Big Endian format):

file:
*********
0040 003f 003d 003b 0038 0033 002e 0028
0022 001b 0013 000c 0004 fffd fff5 ffed
ffe6 ffde ffd8 ffd2 ffcd ffc9 ffc5 ffc3
ffc1 ffc1 ffc1 ffc2 ffc5 ffc8 ffcc ffd1
ffd7 ffde ffe5 ffec fff4 fffc 0003 000b
0013 001a 0021 0028 002e 0033 0037 003b
003d 003f 003f 003f 003e 003b 0038 0034
002f 0029 0023 001c 0014 000d 0005 fffe
fff6 ffee ffe6 ffdf ffd9 ffd3 ffcd ffc9
ffc5 ffc3 ffc1 ffc1 ffc1 ffc2 ffc4 ffc8
ffcc ffd1 ffd7 ffdd ffe4 ffeb fff3 fffb
0002 0a0d 1200 1900 2000 2700 ...
*********

stdout:

*********
0040 003f 003d 003b 0038 0033 002e 0028
0022 001b 0013 000c 0004 fffd fff5 ffed
ffe6 ffde ffd8 ffd2 ffcd ffc9 ffc5 ffc3
ffc1 ffc1 ffc1 ffc2 ffc5 ffc8 ffcc ffd1
ffd7 ffde ffe5 ffec fff4 fffc 0003 000b
0013 001a 0021 0028 002e 0033 0037 003b
003d 003f 003f 003f 003e 003b 0038 0034
002f 0029 0023 001c 0014 000d 0005 fffe
fff6 ffee ffe6 ffdf ffd9 ffd3 ffcd ffc9
ffc5 ffc3 ffc1 ffc1 ffc1 ffc2 ffc4 ffc8
ffcc ffd1 ffd7 ffdd ffe4 ffeb fff3 fffb
0002 000a 0012 0019 0020 0027
*********

If you have a look at the output and the output a hex editor displayed
(opening the file as little endian), you will see that the endianness is
saved correctly, the output is equal. Except for the last line: 0020
still with the output, 000a/0a0d is completely strange (where does this
0d come from?!) and all bytes afterwards are reversed (1200 instead of
0012, 1900 instead of 0019 and so on).

The interesting thing: this happens exactly after one cycle of the
cosine-function that generates the sample data. One cycle later, the
endianness is correct again, and so on.

Where does this strange behaviour come from?

Best regards,
Fabian Lenzen
 
J

Jerry Coffin

[ ... ]
If you have a look at the output and the output a hex editor displayed
(opening the file as little endian), you will see that the endianness is
saved correctly, the output is equal. Except for the last line: 0020
still with the output, 000a/0a0d is completely strange (where does this
0d come from?!) and all bytes afterwards are reversed (1200 instead of
0012, 1900 instead of 0019 and so on).

Not really reversed -- just offset by a byte (because of the 0d that got
inserted). They just look reversed because in this part of the file,
every other byte is a zero.

As far as the 0d byte, my guess is that you opened the file in text mode
(i.e. you didn't specify std::binary when you opened it). You're
probably also running on Windows, where the end of a line is normally
marked by a carriage return/line feed combination. When you tried to
write a new-line (the 0a) the standard library turned it into an end-of-
line marker, though a rather oddball one. Right now, it has the line-
feed followed by the carriage return; you more often see the carriage
return first, though in the end it makes little real difference.

Anyway, as implied above, the cure is to specify std::binary when you
open the file(s).
 
F

Fabian Lenzen

As far as the 0d byte, my guess is that you opened the file in text mode
(i.e. you didn't specify std::binary when you opened it). You're
probably also running on Windows, where the end of a line is normally
marked by a carriage return/line feed combination. When you tried to
write a new-line (the 0a) the standard library turned it into an end-of-
line marker, though a rather oddball one. Right now, it has the line-
feed followed by the carriage return; you more often see the carriage
return first, though in the end it makes little real difference.

Anyway, as implied above, the cure is to specify std::binary when you
open the file(s).

Ah, thank you very much! I didn't know that ios really treats binary and
text data in different ways.
 
V

Victor Bazarov

Fabian said:
Ah, thank you very much! I didn't know that ios really treats binary and
text data in different ways.

It's not the ios itself, it's the system that can introduce differences.
AFAIK, for instance on Un*x systems 'text' and 'binary' are not
different. On MSDOS, Windows, Mac, they are, IIRC.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top