The TransistoriZed logo should be here! But... curses! Your browser does not support SVG!

homelist of postsdocs about & FAQ


Reading raw PCM data files into an array in ANSI C

I am working on the Rx part of the RTTY decoder. The first stage to start with is to find a way to read the encoded by the Tx in my previous post raw PCM file and dump it into an array. A natural act was to look online for already existing code for reading little endian 16-bit raw PCM files, to my surprise a lot about PCM is written out there, but strangely nothing in pure ANSI C which is small and selfcontained enough to be copied and used directly. An equivalent in function ANSI C code I am posting here probably exists out there online, but I will anyway print my implementation here, hopefully anyone would benefit from it. It is also a good way of storing it here for my own reference.

// Reads raw PCM file format and prints the samples in signed integer format on the standard output.
// Initial version A, Deyan Levski, deyan.levski@gmail.com, 15.07.2014
//
//

#include stdio.h
#include stdlib.h
#include math.h
#include string.h

#define SAMPLE_RATE 44100 // Hz
#define BITS_PER_SAMPLE 16 // bits
#define N_SAMPLES 5000 // n

int convertBitSize(unsigned int in, int bps)
{
        const unsigned int max = (1 << (bps-1)) - 1;
        return in > max ? in - (max<<1) : in;
}

int readPCM(int *data, unsigned int samp_rate, unsigned int bits_per_samp, unsigned int num_samp)

{
	FILE *fp;
	unsigned char buf;
	unsigned int i, j;

	fp = fopen("ttyburst.pcm", "r");

        for (i=0; i < num_samp; ++i) {

		unsigned int tmp = 0;

		for (j=0; j != bits_per_samp; j+=8) {
			fread(&buf, 1, 1, fp);
			tmp += buf << j;
		}

		data[i] = convertBitSize(tmp, bits_per_samp);

        }
}

int main(void)
{

	printf("SAMPLE RATE = [%d] BITS PER SAMPLE = [%d] N SAMPLES = [%d]\n", SAMPLE_RATE, BITS_PER_SAMPLE, N_SAMPLES);

	int *data = (int *) malloc(N_SAMPLES * sizeof(int));

        readPCM(data, SAMPLE_RATE, BITS_PER_SAMPLE, N_SAMPLES);

	unsigned int i;
	for (i = 0; i < N_SAMPLES; ++i) {
		printf("%d\n", data[i]);
	}

return 0;

}

Compiles without errors on a standard gcc compiler with standard ANSI C option set. When run, the executable would look for ttyburst.pcm in the root folder and print all samples on the standard output. The raw PCM is assumed to be little endian, signed 16 bit, sampling rate and number of samples are set with the #define statements. Other formats can be supported with minor code modifications.

Date:Tue Jul 15 22:19:53 CEST 2014

Comments

sagar patel
03 Oct 2018, 15:56
I need to convert my 32 bit pcm raw data into float array.By above code i cant get expected output.
Deyan Levski
26 Oct 2018, 09:24
Hi Sagar,

The snippet above produces a 16-bit wave file from a 16-bit PCM file. As I have stated in the last sentence: The raw PCM is assumed to be little endian, signed 16 bit, sampling rate and number of samples are set with the #define statements.

Cheers,
Deyan
*Name:
Email:
Notify me about new comments on this page
Hide my email
*Text: