reading a raw audio file as Matlab does in C - c

I have the following small script that I want to write in C :
`%% getting the spectgrum
clear, clc ;
fileName ='M0.raw'
[x,fs] = audioread(fileName);
[xPSD,f] = pwelch(x,hanning(8192),0,8192*4 ,fs);
plot(f,10*log10(abs(xPSD)));
xlim([0 22e3]);
absxPSD = abs(xPSD);
save('absXPSD.txt','absxPSD','-ascii');
save('xPSD.txt','xPSD','-ascii');
save('xValues.txt','x','-ascii');
save('frequency.txt','f','-ascii');`
without goning in details, I have a problem getting the correct result, when I checked I figured out that the data that I read is wrong here's sample that read the raw file to compare it with what Matalb reads :
#include <stdio.h>
#include <stdlib.h>
int main (){
FILE* inp =NULL;
FILE* oup =NULL;
double value =0;
inp = fopen("M0.raw","r");
oup = fopen("checks.txt","w+");
UPDATE
after LoPiTaL's answer I've tried to jump over the RIFF header which is 44Byte length0 using fseek
fseek (inp,352,SEEK_SET);// that didn't help getting the right result !!
if( inp == NULL || oup==NULL){
printf(" error at file opning \n");
return -1;
}
while (!(feof(inp))){
fread(&value,sizeof(double),1,inp);
printf(" %f \n ",value);
fprintf(oup,"%f\n",value);
}
fclose(inp);
fclose(oup);
return 0;
}
and the result that I get is :
-28083683309813134333858080554409220100578902032859386180468433149049781495379346137536863936326139303879846829175766826833343673613788446579155215033623707200818670767132304934425064429529496303287641688697019947073799877821581901737052884168025721481955133510652655692037990001524306465271815108431928360960.000000
0.000000
0.000000
0.000000
0.000000
0.000000
-20701636078248669570005757343846586744027511881225108933223144646890577802102653022204406730988428912367583701134782419138464527797567258583836429190479797597328678189654150340845........................................................................
and my aim is to get those value :
-1.0162354e-02
-9.3688965e-03
-7.5073242e-03
-1.9531250e-03
3.7231445e-03
1.3549805e-02
2.3223877e-02
3.2867432e-02
4.4830322e-02
5.5114746e-02
6.7291260e-02
7.7636719e-02
8.8562012e-02
9.5794678e-02
1.0055542e-01
1.0415649e-01
1.0351563e-01
1.0235596e-01
9.8785400e-02
9.1796875e-02
8.3648682e-02
7.1594238e-02
the audio file is mono an is 16bit resolution , any idea how can solve this ? thanks for any help

You must open the file in binary mode, for starters. Otherwise you get text mode, which can do translations of line endings, for instance. Not good with binary data.
Binary mode:
inp = fopen("M0.raw", "rb");
^
|
muy
importante

Sure, you cannot read an audio file as is and hope that the data is as you think it is.
Ignoring any coded audio file, which of course you have to decode prior to read it, lets focus in the RAW audio files:
RAW audio files usually are WAV files. WAV files have a .RIFF header at the beginning of the file, which obviously you would have to ignore before reading audio data.
http://en.wikipedia.org/wiki/Resource_Interchange_File_Format
After you have removed the RIFF header, then the data starts.
As you stated, the data is encoded as 16 bit resolution. 16 bit resolution means that 0x0000 is 0.0 and 0xFFFF is 1.0, and the size of the data is only two bytes!
So you have to read two bytes at a time (i.e. with a signed short) and then do the conversion to the range 0 to 1:
signed short ss;
double value;
FILE* inp =NULL;
inp = fopen("M0.raw","rb"); //As stated in other answer, use binary mode!
fseek (inp,44,SEEK_SET); // Only 44 bytes!!
//We already have discarded the header here....
while (fread(&ss, sizeof(signed short) ,1 , inp) == 1){
//Now we have to convert from signed short to double:
value=((double)ss)/(unsigned)0xFFFF;
//Print the results:
printf(" %f \n ",value);
fprintf(oup,"%f\n",value);
}
Of course, the function "audioread" from Matlab already does all of this for you, so you don't have to care about the encoding, as in your example, your particular data is in 16 bit, but if you use any other file, it could be 8, 16, 24 or 32, even could be differential or be encoded despite being a WAV file (see the RIFF header for more information).

Related

Reading a specific sector from a hard drive using C on Linux (GNU/Linux )

I know that a hard drive are system's files (/dev/sdXX) –then treated like files-, I have questions about this:
I tried those following lines of code but nothing positive
-------first attempt----------
int numSecteur=2;
char secteur [512];
FILE* disqueF=fopen("/dev/sda","r"); //tried "rb" and sda1 ...every thing
fseek(disqueF, numSecteur*512,SEEK_SET);
fread(secteur, 512, 1, disqueF);
fclose(disqueF);
-------Second attempt----------
int i=open("/dev/sda1",O_RDONLY);
lseek(i, 0, SEEK_SET);
read(i,secteur,512);
close(i);
------printing the results----------
printf("hex : %04x\n",secteur);
printf("string : %s\n",secteur);
Why the size is of the file /dev/sda1 is just 8 KBytes ?
How the data is stored (binary or hex….) "for the printing"
Please, I need some clues, and if someone need more details just he ask.
Thanks a lot.
Ps: Running kali 2 64bits ”debian” on VMware and i am RooT.
I tried those following lines of code but nothing positive
That's not a question.
Why the size is of the file /dev/sda1 is just 8 KBytes ?
That isn't the file size, it's the device number. (There are two parts, so the device number of sda1 is 8,1)
How the data is stored (binary or hex….) "for the printing"
Data isn't "stored for the printing". Data is stored (in electrical voltages representing binary, but you don't need to know that), and you can print it any way you want.
You cannot printf() array of chat like that, you need right print result. For example as hex dump:
for (int i = 0; i < sizeof(secteur); i++) {
printf ("%02x ", secteur[i]);
if ((i + 1) % 16 == 0)
printf ("\n");
}

Encoding a wav file using G711 encoding

I am trying to encode a PCM uncompressed Wav file using A law encoding.
I have written a function which takes in the 16 bit PCM data and returns 8 bit encoded data..After encoding, my file does not play properly..I feel that there is something I am not doing correctly to handle the files.I have separated the header information of the file and written the same header to output file.
// Code for compressing data is below
short inbuff;
unsigned char outbuff;
while (!feof(inp))
{
fread(inbuff, 2 , BUFSIZE, inp);
for (i=0; i < BUFSIZE; ++i)
{
temp_16 = inbuff[i];
temp_8 = Lin2Alaw(temp_16);
outbuff[i] = temp_8;
}
fwrite(outbuff, 1 , (BUFSIZE), out);
}
You are writing the data with the same header, which means that any audio program will think the data inside the WAV file is still PCM. Check the file format for WAV and change it accordingly.
Mainly you need to change audio format at 0x0014-0x0015 to a-law and other values also to mark the proper bytes per second, block size etc.
Easiest way to make sure they're correct might be to convert the file with an audio editor and then checking for the differences in the values.
How did your code even compile when you are not using arrays? Even so, your use of feof isn't good, please see Why is “while ( !feof (file) )” always wrong?
#include <stdio.h>
#define BUFSIZE 512
int main(void) {
short inbuff[BUFSIZE]; // must be an array
unsigned char outbuff[BUFSIZE]; // must be an array
size_t bread, i;
unsigned char temp_8;
short temp_16;
FILE *inp, *out;
// ... open the file
// ... transcribe the header
// rewrite the data
while ((bread = fread(inbuff, 2 , BUFSIZE, inp)) > 0)
{
for (i=0; i < bread; ++i) // only the data actually read
{
temp_16 = inbuff[i];
temp_8 = Lin2Alaw(temp_16);
outbuff[i] = temp_8;
}
fwrite(outbuff, 1 , bread, out); // only the data actually read
}
// ... finish off and close the file
return 0;
}
I notice too you are using signed short for the 16-bit data - should that be unsigned short?
See the format of wave file is at
http://www.topherlee.com/software/pcm-tut-wavformat.html
Now check all bytes of header and make sure all information about bit rate,sample rate etc are correct.
If your code for compressing is correct then issue should be with header file only.

Writing large binary file part by part

I am trying to do a fairly easy task but am stumped by how the FILE* works. So I am writing a binary file (las file) which has a header and then the points in binary format. Since this is a huge file, I am doing it part by part. But the problem comes when the file pointer writes almost 3/4th of the file correctly and then gives entirely wrong file position pointer.
//struct points written to
struct las_points{
float x;
float y;
float z;
float time;
};
int writepoints(){
outfilename = "pointcloud_13.las";
fout = fopen(outfilename,"wb+");
// numPts - total number of points to be processed
// numRec - number of records processed every time
numRec = numPts/4;
las_points *lp;
// ending size of the file
int endSize = 0,j=0;
// header is written
// endSize = 233
for(i=0;i<numPts;i+=numRec){
lp = (las_points*)malloc(sizeof(las_points)*numRec);
// some processing done
printf("Iteration - %d\n",j);
lasWritePoints(lp,fout,numRec,endSize);
fflush(fout);
free(lp);
lp = NULL;
}
fclose(fout);
}
int lasWritePoints(las_points*lp, FILE* fout,int numRec,int &endSize){
if(!fout || !lp){
printf("File couldnt be written \n");
exit(1);
}
printf("endSize - %d \n",endSize);
fseek(fout,endSize,SEEK_SET);
for(int i=0;i<numRec;i++) {
fwrite(&lp[i].x,sizeof(float),1,fout);
fwrite(&lp[i].y,sizeof(float),1,fout);
fwrite(&lp[i].z,sizeof(float),1,fout);
fseek(fout,8,SEEK_CUR);
fwrite(&lp[i].time,sizeof(float),1,fout);
}
endSize = ftell(fout);
printf("endSize - %d \n",endSize);
}
Only the writing of the binary file is reproduced. The problem is that for the first four iterations for a file, it runs smoothly. Then at the end of last iteration, the endSize it gives is lesser than the beginning endSize.
Output:
Total size of file to be read: 1258456752
Iteration : 0
endSize : 233
endSize : 550575041
Iteration : 1
endSize : 550575041
endSize : 1101149849
Iteration : 2
endSize : 1101149849
endSize : 1651724657
Iteration : 3
endSize : 1651724657
endSize : 54815783
Can someone point out what I am doing wrong?
You are writing more bytes than can be represented by a 32-bit int (about 2 billion = 2 GB). Use a long to store the results of ftell():
long endSize = ftell(fout);
printf("endSize - %ld\n", endSize);
You need to dereference endSize.
You are assigning the file size/position to a pointer resulting in your unexpected behavior.
endSize = ftell(fout);
s/b
*endSize = ftell(fout);
This is one of the most common mistakes in C.
You are probably getting stuck with the 32-bit versions of file access functions. What platform/compiler/file system are you using?
If you are on:
Linux using gcc try adding -D_FILE_OFFSET_BITS=64 to your compiler command
Windows using mingw try using fseeko and ftello
a 32-bit Windows with Visual C++ try using _open (not quite a drop-in replacement)
a file system that has a 2GB file size limit then my condolences

Audio samplerate converter using libsndfile and libsamplerate. Not sure if using function src_simple correctly

I have been building a simple samplerate converter in c using libsndfile and libsamplerate. I just cant seem to get the src_simple function of libsamplerate to work, whatever I try. I have striped back my code to be as simple as possible and it now just outputs a silent audio file of identical sampling rate:
#include <stdio.h>
#include <sndfile.h>
#include <samplerate.h>
#define BUFFER_LEN 1024
#define MAX_CHANNELS 6
int main ()
{
static double datain [BUFFER_LEN];
static double dataout [BUFFER_LEN];
SNDFILE *infile, *outfile;
SF_INFO sfinfo, sfinfo2 ;
int readcount ;
const char *infilename = "C:/Users/Oli/Desktop/MARTYTHM.wav" ;
const char *outfilename = "C:/Users/Oli/Desktop/Done.wav" ;
SRC_DATA src_data;
infile = sf_open (infilename, SFM_READ, &sfinfo);
outfile = sf_open (outfilename, SFM_WRITE, &sfinfo);
src_data.data_in = datain
src_data.input_frames = BUFFER_LEN;
src_data.data_out = dataout;
src_data.output_frames = BUFFER_LEN;
src_data.src_ratio = 0.5;
src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
while ((readcount = sf_read_double (infile, datain, BUFFER_LEN)))
{
src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1);
sf_write_double (outfile, dataout, readcount) ;
};
sf_close (infile);
sf_close (outfile);
sf_open ("C:/Users/Oli/Desktop/Done.wav", SFM_READ, &sfinfo2);
printf("%d", sfinfo2.samplerate);
return 0;
}
It's really starting to stress me out. The program is a uni project and is due very soon, it is making me very anxious as whatever I try seems to result in failure. Can anyone please help me?
I'm not an expert on this particular library, but just from looking at the online documentation I see a few problems with your code:
src_simple apparently works with floats, yet your buffers are doubles - I think you need to change the buffers to float and use sf_read_float/sf_write_float for I/O.
src_simple is the "simple" interface and is intended to be applied to an entire waveform in one call, not in chunks as you are doing - see http://www.mega-nerd.com/SRC/faq.html#Q004 - you should first get the input file size, then allocate sufficient memory, read in the whole file, convert it in one go, then write the converted output data to your output file.
when changing sample rate you will get a different number of samples in the output file than in the output file (around half as many in for case), yet you're writing the same number of samples that you read (readcount). You should probably be using src_data.output_frames_gen as the number of frames to write, not readcount.

Jpeglib code gives garbled output, even the bundled example code?

I'm on Ubuntu Intrepid and I'm using jpeglib62 6b-14. I was working on some code, which only gave a black screen with some garbled output at the top when I tried to run it. After a few hours of debugging I got it down to pretty much the JPEG base, so I took the example code, wrote a little piece of code around it and the output was exactly the same.
I'm convinced jpeglib is used in a lot more places on this system and it's simply the version from the repositories so I'm hesitant to say that this is a bug in jpeglib or the Ubuntu packaging.
I put the example code below (most comments stripped). The input JPEG file is an uncompressed 640x480 file with 3 channels, so it should be 921600 bytes (and it is). The output image is JFIF and around 9000 bytes.
If you could help me with even a hint, I'd be very grateful.
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include "jpeglib.h"
#include <setjmp.h>
int main ()
{
// read data
FILE *input = fopen("input.jpg", "rb");
JSAMPLE *image_buffer = (JSAMPLE*) malloc(sizeof(JSAMPLE) * 640 * 480 * 3);
if(input == NULL or image_buffer == NULL)
exit(1);
fread(image_buffer, 640 * 3, 480, input);
// initialise jpeg library
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
// write to foo.jpg
FILE *outfile = fopen("foo.jpg", "wb");
if (outfile == NULL)
exit(1);
jpeg_stdio_dest(&cinfo, outfile);
// setup library
cinfo.image_width = 640;
cinfo.image_height = 480;
cinfo.input_components = 3; // 3 components (R, G, B)
cinfo.in_color_space = JCS_RGB; // RGB
jpeg_set_defaults(&cinfo); // set defaults
// start compressing
int row_stride = 640 * 3; // number of characters in a row
JSAMPROW row_pointer[1]; // pointer to the current row data
jpeg_start_compress(&cinfo, TRUE); // start compressing to jpeg
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
// clean up
fclose(outfile);
jpeg_destroy_compress(&cinfo);
}
You're reading a JPEG file into memory (without decompressing it) and writing out that buffer as if it were uncompressed, that's why you're getting garbage. You need to decompress the image first before you can feed it into the JPEG compressor.
In other words, the JPEG compressor assumes that its input is raw pixels.
You can convert your input image into raw RGB using ImageMagick:
convert input.jpg rgb:input.raw
It should be exactly 921600 bytes in size.
EDIT: Your question is misleading when you state that your input JPEG file in uncompressed. Anyway, I compiled your code and it works fine, compresses the image correctly. If you can upload the file you're using as input, it might be possible to debug further. If not, I suggest you test your program using an image created from a known JPEG using ImageMagick:
convert some_image_that_is_really_a_jpg.jpg -resize 640x480! rgb:input.jpg
You are reading the input file into memmory compressed and then you are recompressing it before righting to file. You need to decompress the image_buffer before compressing it again. Or alternativly instead of reading in a jpeg read a .raw image
What exactly do you mean by "The input JPEG file is an uncompressed"? Jpegs are all compressed.
In your code, it seems that in the loop you give one row of pixels to libjpeg and ask it to compress it. It doesn't work that way. libjpeg has to have at least 8 rows to start compression (sometimes even more, depending on parameters). So it's best to leave libjpeg to control the input buffer and don't do its job for it.
I suggest you read how cjpeg.c does its job. The easiest way I think is to put your data in a raw type known by libjpeg (say, BMP), and use libjpeg to read the BMP image into its internal representation and compress from there.

Resources