LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

void array 3 bytes into integer (4 byte) array (WAV file reading)

I am creating a program that reads in a WAV file and will eventually do some Advanced Analysis on it.

 

I have been successful in copying out 8 and 16 bit info since i can save these directly into a char and short int array respectfully.  however, performing 24-bit has posed to be kind of tricky and i am NOT that great of a bit shifter.  Can someone please explain which annotation of shifting I need to do to save 3 consecutive bytes ( a 24-bit number) into an integer32 space?  Not sure if Wav file format knowledge is needed but here is a link: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

 

Below is the exert from my code.  I am unsure about the 24-bit memcpy.  And i think i need to do a (data[i])&0x00FF)-127 to the 8 bit portion since its unsigned (but not sure if what I just typed is correct either).

 

THANKS IN ADVANCE

 

 

//ReadWavFile and save data into channel 1/2 array

 

#include <formatio.h>
#include <ansi_c.h>
#include <lowlvlio.h>
#include "WavFileIO.h"

int Snd_ReadWavFile(char *filePath, void *channel1, void *channel2, int bytesPerChannel)
{
	// Information about the Wav file.
	int samplesPerChannel;
	int bitsPerSample;
	int numberOfChannels;
	int samplingFrequency;
	int checkBytesPerChannel;
	header *wavHeader;
	int file;
	int error;
	int i;
	unsigned char* data;
	int fileSize;
	
	// Get information about the file.
	error = Snd_ReadWavFileInfo(filePath, &samplesPerChannel, &bitsPerSample, &numberOfChannels, 
		&samplingFrequency, &checkBytesPerChannel);
	if(error < 0)
		return -1; // ReadWavFileInfo error.

	// Simple error check
	if(checkBytesPerChannel != bytesPerChannel)
		return -1; // Error: BytesPerChannel does not match file.
		
	if(!channel1)
		return -1; // channel1 is null
	
	if(!channel2 && (numberOfChannels == 2))
		return -1; // channel2 is null		
	
	// Open file for reading.
	file = OpenFile (filePath, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_BINARY);
	if(file < 0)
	{
		return -1; // OpenFile error.
	}
	
	// Skip the header since we already have the info from it.
	/*if(lseek (file, sizeof(header), SEEK_SET))
	{
		CloseFile(file);
		return -1; // Seeking error.
	}*/
	wavHeader = malloc(sizeof(header));
	ReadFile (file, (char *)wavHeader, sizeof(header));
	free(wavHeader);
	
	// Read the data
	data = malloc((bitsPerSample/8)*samplesPerChannel*numberOfChannels);
	if(!data)
	{
		CloseFile(file);
		return -1; // Memory allocation error.
	}	

	GetFileInfo (filePath, &fileSize);			
	data = malloc(fileSize-sizeof(header));
	error =	ReadFile (file, data, fileSize-sizeof(header));
	//error = ReadFile (file, data, (bitsPerSample/8)*samplesPerChannel*numberOfChannels);
	if(error < 0)
	{
		free(data);
		CloseFile(file);
		return -1; // ReadFile error.   
	}
	
	// Process the data
	// We have to treat data differently depending on how many bits per sample it has.
	switch(bitsPerSample)
	{
		// 8 bit data.
		case 8:
			for(i = 0; i < samplesPerChannel; i++)
			{
				memcpy((void*)((char*)channel1+i), &data[i*numberOfChannels], 1);
				if(numberOfChannels == 2)
				{
					memcpy((void*)((char*)channel2+i), &data[i*numberOfChannels+1], 1);
				}	
			}
			break;
			
		// 16 bit data.	
		case 16:
	   		for(i = 0;i < samplesPerChannel; i++)
			{
				memcpy((void*)((char*)channel1+i*2), &data[i*2*numberOfChannels], 2);
				if(numberOfChannels == 2)
				{
					memcpy((void*)((char*)channel2+i*2), &data[i*2*numberOfChannels+2], 2);
				}	
			}
			break;
		
		// 24 bit data.
		case 24:	   //Must be saved into an integer size
	   		for(i = 0;i < samplesPerChannel; i++)
			{
				memcpy((void*)((char*)channel1+i*4), &data[i*3*numberOfChannels], 3);	    //every 4 bytes so it in integer format
				if(numberOfChannels == 2)
				{
					memcpy((void*)((char*)channel2+i*4), &data[i*3*numberOfChannels+3], 3);
				}	
			}	  
			break;
		
		// Unsupported number of data bits.
		default:		
			free(data);
			CloseFile(file);
			return -1; // Unsupported number of data bits.
			break;
	}
	free(data);
	error = CloseFile(file);
	if(error < 0)
		return -1; // Error while closing file.
	return 0;
}

 

 

0 Kudos
Message 1 of 6
(5,276 Views)

Hi ngay,

you may find something similar to what you want in my Color-to-grayscale conversion example program: specifically ConvertFile () and ConvertBMP () functions handle 24-bit bitmaps casting image data into an array of integers. You may take them as a starting point to develop your own converting function.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 6
(5,269 Views)

Hi,

    i recomend to not use memcpy for copying 1..3 bytes there is too much overhead in function call.

    i am not sure about waw but according to:

    http://cboard.cprogramming.com/c-programming/101753-reading-16-24-bit-audio-data-into-32-bit-integer...

 

   this can be somethink like(not tested)

24bit to 32bit:

         chanel1:((char*)channel1+i*4 +0)=data[0+i*4*numberOfChannels +0];

                 ((char*)channel1+i*4 +1)=data[0+i*4*numberOfChannels +1];

                 ((char*)channel1+i*4 +2)=data[0+i*4*numberOfChannels +2];

                 ((char*)channel1+i*4 +3)=data[0+i*4*numberOfChannels +3];//copy last byte form 24bit to 32bit

         chanel2:((char*)channel2+i*4 +0)=data[4+i*4*numberOfChannels +0];

                 ((char*)channel2+i*4 +1)=data[4+i*4*numberOfChannels +1];

                 ((char*)channel2+i*4 +2)=data[4+i*4*numberOfChannels +2];

                 ((char*)channel2+i*4 +3)=data[4+i*4*numberOfChannels +3];//copy last byte form 24bit to 32bit

 

        copying last byte form 24bit to 32bit is for getting good min/max value

        for example:

        0x000000  ->0x00000000 //minimal value is minimal value

        0xFFFFFF->0xFFFFFFFF //max value is max value

        0x7F7F7F ->0x7F7F7F7F //Half value is max value

        it is only optimization you ca set last byte to zero, if you like, or you can invent your own optimiyzation algorithm

 

also for example..

   8bit:

         chanel1:((char*)channel1+i)=data[0+i*numberOfChannels];

         chanel2:((char*)channel2+i)=data[1+i*numberOfChannels+1];

   16bit:

         chanel1:((char*)channel1+i*2 +0)=data[0+i*2*numberOfChannels +0];

         ((char*)channel1+i*2 +1)=data[0+i*2*numberOfChannels +1];

         chanel2:((char*)channel2+i*2 +0)=data[2+i*2*numberOfChannels +0];

                 ((char*)channel2+i*2 +1)=data[2+i*2*numberOfChannels +1];

0 Kudos
Message 3 of 6
(5,219 Views)

ia am sorry, in previous post i switch byte order for copy least signifcant byte in 24bit

 there is corected version:

 

    i recomend to not use memcpy for copying 1..3 bytes there is too much overhead in function call.

    i am not sure about waw but according to:

    http://cboard.cprogramming.com/c-programming/101753-reading-16-24-bit-audio-data-into-32-bit-integer...

 

   this can be somethink like(not tested)

24bit to 32bit:

         chanel1:((char*)channel1+i*4 +0)=data[0+i*4*numberOfChannels +0];//copy

                 ((char*)channel1+i*4 +1)=data[0+i*4*numberOfChannels +0];

                 ((char*)channel1+i*4 +2)=data[0+i*4*numberOfChannels +1];

                 ((char*)channel1+i*4 +3)=data[0+i*4*numberOfChannels +2];


         chanel2:((char*)channel2+i*4 +0)=data[4+i*4*numberOfChannels +0];//copy

                 ((char*)channel2+i*4 +1)=data[4+i*4*numberOfChannels +0];

                 ((char*)channel2+i*4 +2)=data[4+i*4*numberOfChannels +1];

                 ((char*)channel2+i*4 +3)=data[4+i*4*numberOfChannels +2];

 

        copying last byte form 24bit to 32bit is for getting good min/max value

        for example:

        0x000000  ->0x00000000 //minimal value is minimal value

        0xFFFFFF->0xFFFFFFFF //max value is max value

        0x7F7F7F ->0x7F7F7F7F //Half value is max value

        it is only optimization you ca set last byte to zero, if you like, or you can invent your own optimiyzation algorithm

 

also for example..

   8bit:

         chanel1:((char*)channel1+i)=data[0+i*numberOfChannels];

         chanel2:((char*)channel2+i)=data[1+i*numberOfChannels+1];

   16bit:

         chanel1:((char*)channel1+i*2 +0)=data[0+i*2*numberOfChannels +0];

         ((char*)channel1+i*2 +1)=data[0+i*2*numberOfChannels +1];

         chanel2:((char*)channel2+i*2 +0)=data[2+i*2*numberOfChannels +0];

                 ((char*)channel2+i*2 +1)=data[2+i*2*numberOfChannels +1];

0 Kudos
Message 4 of 6
(5,211 Views)

I have yet to test it, but I made soem corrections below:

 

 

//memcpy((void*)((char*)channel1+i*4), &data[i*3*numberOfChannels], 3);
					((char*)channel1+i*4+0)=data[i*3*numberOfChannels+0];//copy
((char*)channel1+i*4+1)=data[i*3*numberOfChannels+0];
((char*)channel1+i*4+2)=data[i*3*numberOfChannels+1];
((char*)channel1+i*4+3)=data[i*3*numberOfChannels+2];
					
					
					
					
if(numberOfChannels == 2)
{
//memcpy((void*)((char*)channel2+i*4), &data[i*3*numberOfChannels+3], 3);
((char*)channel2+i*4 +0)=data[3+i*3*numberOfChannels +0];//copy
((char*)channel2+i*4 +1)=data[3+i*3*numberOfChannels +0];
((char*)channel2+i*4 +2)=data[3+i*3*numberOfChannels +1];
((char*)channel2+i*4 +3)=data[3+i*3*numberOfChannels +2];
}

 

 

 

0 Kudos
Message 5 of 6
(5,162 Views)

sorry, you has right. I made it from scratch, but you got the point. Smiley Happy

0 Kudos
Message 6 of 6
(5,149 Views)