On reading/writing binary files using Matlab
I spent most of my time yesterday trying to debug this problem I had with reading and writing binary files using Matlab. For my thesis, I have a copy of the C program that simulates the 2.4 kbps MELP Proposed Federal Standard speech coder from Texas Instruments, Inc. This code can output either compressed speech (output of the decoder) or the bit stream (output of the encoder). I needed to access the bit stream as I had to simulate an AWGN (Additive White Gaussian Noise) Channel and BPSK (Binary Phase Shift Keying) Modulation/Demodulation.
Using Matlab I used the command,
dos([pwd '\melp\melp -a -i ' lb_filename ' -o ' lb_bitstream], ‘-echo’);
to execute the melp code’s analysis (or encoding) stage only, where the filenames of the input and the bit stream are stored in lb_filename and lb_bitstream, respectively. This part was easy, after one click, then I already have my bit stream… It was also easy to read the bits, the command fread does that, but how to write the bits back was where I encountered a problem.
I executed the following lines of code to read my bits in the binary file lb_bitstream.
fid = fopen(lb_bitstream, ‘rb’);
bits_int16 = fread(fid, ‘uint16′);
fclose(fid);
The lines meant that the bits will be read in groups of 16 and will represent a 16-bit unsigned integer. I had to bring these values into their binary counterparts using the dec2bin command. However, dec2bin provides the output in char format, and they needed to be converted back to numerical format using str2num command. Here I have my bits (in 1’s and 0’s) and then I was already able to simulate the AWGN channel and the BPSK modulation/demodulation.
The output of the BPSK demodulator was still, of course, in 1s and 0s. I tried writing these bits to the file directly using fwrite(fid,bits,’uint16’) but as soon as I used this new bit stream as my input to the melp decoder, all I got was noise! I was thinking that the fwrite command would, on its own, group the bits by 16 since one of the parameters in the fwrite command was the format which in this case was uint16. But no…
So… I had to form these bits into groups of 16 again then convert it to its decimal counterpart before executing the fwrite command. The tricky part was the bin2dec command only accepts char or string as inputs. I solved this problem using the following lines of code and when I fed the new lb_bitstream to the melp decoder, I got what I wanted!
Yay!
% convert the bits to uint16 for writing to file
BPSK_demod = reshape(BPSK_demod, 16,length(BPSK_demod)/16);
temp_bpsk = num2str(BPSK_demod’);
temp_bpsk = temp_bpsk(:,1:3:end);
BPSK_demod = bin2dec(temp_bpsk);
fid = fopen(lb_bitstream, ‘wb’);
fwrite(fid, BPSK_demod,‘uint16′);
fclose(fid);
To encode the bits using the melp decoder code (from Texas Instruments), the following code was executed:
dos([pwd '\melp\melp -s -i ' lb_bitstream ' -o ' lb_outfile], ‘-echo’);
And since the melp coder file contains data in int16 format (-32768 to +32767), it has to be converted and scaled back to ±1 using the following lines of code:
fid = fopen(lb_outfile, ‘r’);
lowerband_output = fread(fid, ‘int16′);
fclose(fid);
lb_synth= lowerband_output/32768;
So there you go!
I won the battle with the bits and got the output that I wanted!