Copying audio file, issue with pointers - c

I was wondering if someone could help me with a problem that I'm having. I'm fairly sure that it's a pointer issue (read: I'm VERY much a C beginner), but I've been struggling with it for a fair while and have been unable to fix the issue (despite reading reference pages).
My code is meant to copy a .WAV file using two functions (the function prototypes are fixed). First it reads the file, then it writes a new file using the data samples from the old file. The header is defined in "R_WAV.h" as a typedef struct. The code is run from this:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include "R_WAV.h"
//Function Declarations
int read_WAV(header_type *header, char **data, char *filename);
int write_WAV(header_type *header, char *data, char *filename);
int main()
{
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
char **data;
read_WAV(header, data, *filename);
}
//Run write_WAV
{
header_type *header;
char *filename[] = {//Various files};
char *data;
write_WAV(header, data, *filename);
}
//Run read_WAV again on new files to ensure header info is valid
{
header_type *header;
char *filename[] = {//output files from write};
char *data;
read_WAV(header, data, *filename);
}
return(0);
}
The read_WAV function I've written (abbreviated slightly) is:
int read_WAV(header_type *header, char **data, char *filename)
{
unsigned char buffer4[4];
unsigned char buffer2[2];
FILE *fp = fopen(filename, "rb"); //Open file
//Code here that checks if file successfully opened
//If file valid, find length of file
fseek(fp, 0L, SEEK_END); //Place position at EoF
int size = ftell(fp); //Read the current value
rewind(fp); //Reset position
//Code here that checks if file size < min. header size, if true exits
header = (void*)malloc(size);
//Reading RIFF string
fread(header->ChunkID, sizeof(header->ChunkID), 1, fp);
printf("\nChunkID: %s \n", (header->ChunkID));
And so on, until it comes time to read the data:
//Read DATA samples
char *buffer_data = (char*)malloc(header->Subchunk2Size);
fread(buffer_data,1,(header->Subchunk2Size),fp);
//Error checking code here for if buffer==NULL
*data = buffer_data;
fclose(fp);
return(1);
}
The write_WAV function is:
int write_WAV(header_type *header, char *data, char *filename)
{
char n_file[50]; //Init. for new filename
int data_size = header->Subchunk2Size; //Hold size of data chunk
//CODE TO ALTER FILENAME (working properly)
//Open new file (COPY_of_filename)
FILE * fp_w = fopen(n_file, "wb");
//Check to see if file was successfully created
if (fp_w==NULL)
{
printf("\nUnable to create file.");
return(-1);
}
//Write header to new file (first 44 bytes)
fwrite(header, 1, 44, fp_w);
//Write data to new file
fwrite(data, 1, data_size, fp_w);
fclose(fp_w);
return (1);
}
I'm running into two main issues:
1) I can only get the header info (first 44 bytes) to write properly in write_WAV() if I open one of the .WAV files in that function, then use fread and a buffer to store it. Does it have to be done this way? Is there another way to use the *header that will result in this data being accessible from read_WAV() without needing to reopen the old file in write_WAV()?
2) I can't get the data samples to copy over properly. Even when I read in the header as above (and check that the header info is all correct), all I get is corrupt noise upon opening the new file. I've been trying to research this, but I've gotten nowhere. Could someone help explain/point to the mistakes in what I've done, and what I need to do in order to resolve them?
I know this is really simple stuff, and I wish that my brain was working enough to figure it out by myself. Like I said, I've read reference pages, but I'm still not getting anywhere. Not really firing on all cylinders right now.
Thank you for any (much needed) assistance!

Your problem is the block scoping of data in main in a few places.
That is, when you read in the file, because of variable scoping, you lose the pointer to the data. That is, when you do the write, the pointer it uses points to random memory.
I think you also have the same problem for the header pointer [although I didn't address that issue below, the fix would be similar]. Also, note that in the two read blocks, the type used for header is inconsistent even though they do the same thing.
Here's a version annotated with the bugs:
int main()
{
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
// NOTE/BUG: this is scoped to _this_ block, so the write section below won't
// see it
// NOTE/BUG: this should be char *data and the function call should use &data
char **data;
read_pcm_wavefile(header, data, *filename);
}
//Run write_WAV
{
pcm_wavefile_header_type *header;
char *filename[] = {//Various files};
// NOTE/BUG: this scoped 'data' declaration has none of the data in the read
// sectioon above
char *data;
write_pcm_wavefile(header, data, *filename);
}
//Run read_WAV again on new files to ensure header info is valid
{
pcm_wavefile_header_type *header;
char *filename[] = {//output files from write};
char *data;
read_pcm_wavefile(header, data, *filename);
}
return(0);
}
Here's a fixed version:
int main()
{
char *data;
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
read_pcm_wavefile(header, &data, *filename);
}
//Run write_WAV
{
pcm_wavefile_header_type *header;
char *filename[] = {//Various files};
write_pcm_wavefile(header, data, filename[0]);
}
free(data);
//Run read_WAV again on new files to ensure header info is valid
{
pcm_wavefile_header_type *header;
char *filename[] = {//output files from write};
read_pcm_wavefile(header, &data, filename[0]);
}
return(0);
}
UPDATE:
I've fixed that up. Still unable to get a proper output, which I'm thinking is in the passing of the data/pointer from each function?
As I mentioned you need to do the same for header because main needs the pointer to be filled in by your read function. As it is, after the read call, the value of header in main is unchanged (i.e. not updated by read_WAV as you'd like).
Change:
int read_WAV(header_type *header, char **data, char *filename)
Into:
int read_WAV(header_type **header, char **data, char *filename)
And, make all corresponding adjustments in main and read_WAV
Also, apply the same scoping fix in main for header that was done for data (i.e. header should not be block scoped, but, rather function scoped).
Because, even with the prototype change to read_WAV, main would lose the header value that read_WAV tried to pass back and write_WAV would get a garbage header pointer.
After you get this working, think about the temporal duration of the block scoped variables vs function scoped variables. In other words, if you set a variable, when does the value "go out of scope" [and become invalid].
For comparison, here's a version that does not use block scoped variables:
int
main(void)
{
char *data;
header_type *header;
char *infiles[FILECOUNT] = {//Various files};
char *outfiles[FILECOUNT] = {//Various files};
for (int fidx = 0; fidx < FILECOUNT; ++fidx) {
//Run read_WAV
read_pcm_wavefile(&header, &data, infiles[fidx]);
//Run write_WAV
write_pcm_wavefile(header, data, outfiles[fidx]);
free(header);
free(data);
//Run read_WAV again on new files to ensure header info is valid
read_pcm_wavefile(&header, &data, outfiles[fidx]);
free(header);
free(data);
}
return 0;
}

Related

Structure as a parameter of extern function C

I have to read a text file using this structure. Also, I have to use external functions. I made the code for file reading and it works in main function.
Text file:
banana 3 orange 8 music 9- first character is a blank space*
#include <stdio.h>
#include <stdlib.h>
struct file
{
char name[30];
char size;
};
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",&f[n].name,&f[n].size);
n++;
}
}
But when I try to make this reading using another c file and extern function it's no working.. :(
This is what is written in filereading.c:
void fileReading(struct file *f[30], FILE *files)
{
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",&f[n].name,&f[n].size);
n++;
}
}
And fileReading.h:
void fileReading(struct fisier *, FILE *);
And in main.c:
#include <stdio.h>
#include <stdlib.h>
struct file
{
char name[30];
char size;
};
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
fileReading(f[30],files);
}
When I compile it, it says:
request for member 'name' in something not a structure or union
request for member 'size' in something not a structure or union|
||=== Build finished: 2 errors, 2 warnings (0 minutes, 0 seconds) ===||
Can you help me, please? Thank you!
From what I see it looks like you do not have a good understanding of pointers.
These changes should solve your problem:
void fileReading(struct file *f, FILE *files)
{
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",f[n].name,&f[n].size);
//printf("%s %c",f[n].name,f[n].size);
n++;
}
}
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
fileReading(f,files);
}
What you did wrong:
void fileReading(struct file *f[30], FILE *files) //here you were saying file is a **
fscanf(files,"%s %c",&f[n].name,&f[n].size); // here you need to send the a char* but you were sending a char ** as a second parameter
fileReading(f[30],files); // here you were sending the 31th element of the structure array f which by the way doesn't exist (indexing is from 0 , f[29] is the last) even though that was not what you wanted to do in the first place
The file fileReading.c doesn't know the definition of struct file. You need to move it from main.c to fileReading.h and #include "fileReading.h" in both main.c and fileReading.c.
Also, the definition and call of fileReading is incorrect. Instead of:
void fileReading(struct file *f[30], FILE *files)
You want:
void fileReading(struct file *f, FILE *files)
And you call it like this:
fileReading(f,files);
This is incorrect:
fileReading(f[30],files);
Because you're passing a single struct file instead of the array, and the single instance you're passing is one element off the end of the array (since the size is 30, valid indexes are 0-29), which can cause indefined behavior.

c - copy_to_user: how to read a struct type value of kernel space in the user space?

I have a kernel module where I would like to pass some values into User Space. Someone suggested me to use struct type to pass more values.
In kernel space I have:
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
static ssize_t sample_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
int ret = 1;
int delta = 10;
data_t val;
val.val_btn_status = gpio_get_value( BTN );
val.val_delta = delta;
copy_to_user( buffer, &val, sizeof(data_t));
return( ret );
}
In User space how can I take the two values into data_t struct?
I thought to declare also in User Space the data_t type as:
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
int main(int argc, char **argv)
{
data_t str;
char *app_name = argv[0];
char *dev_name = "/dev/sample";
int fd = -1;
if ((fd = open(dev_name, O_RDWR)) < 0)
{
fprintf(stderr, "%s: unable to open %s: %s\n", app_name, dev_name, strerror(errno));
return( 1 );
}
x = read(fd, &str, 1);
return 0;
}
but I don't like this because I wouldn't like to rewrite both on User Space and on Kernel Space the same typedef, and maybe this one doesn't work. There are other solutions?
You can add the common struct and the dev_name in to a header and include in the driver and the user space program.
Like: data.h
#ifndef DATA_H
#define DATA_H
typedef struct data {
int val_delta;
int val_btn_status;
}data_t;
#define dev_name "/dev/sample"
#endif
Also change
read(fd, &str, 1);
to
read(fd, &str, sizeof(data_t));
Firstly, you need to understand the copy_to_user() def.
unsigned long copy_to_user ( void __user * to,
const void * from,
unsigned long n);
In your sample sample_read() function should use char __user *buffer instead of char *buffer.
Put your typedef struct data definition into a header file which can be included both kernel module and user program instead of redefining it twice.
Refer to thread
Have you tried other options, like marking your ECHO interrupt from the sensor (I'm assuming that it'll be an interrupt) as a fast interrupt so it won't be pre-empted by others at the same level.
Or why not have it at the highest available interrupt level on your processor (beneath the hard coded ones).
As Santosh says there has to be a different reason for the freeze. Perhaps have you looked at the alignment of your given structure? In accordance to your underlying processor's word length??

C Function pointer parameter not the same when function exits

I am having a problem with passing a pointer to a function. When the function returns the pointer seems to be different than what it is in the function.
So I pass a pointer to the function which gets raw image data which should then be stored in the memory referenced by the pointer.
If I then pass the pointer from inside the raw image function to a function to create a JPEG file from the raw data then it works correctly.
If I first wait for the raw image function to finish and then call the JPEG function using the pointer I passed to the raw image function then it fails to create the image.
A simplified version of the code is below:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData = NULL;
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
getRawImage(rawData);
// This does not work
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
// This Works!!
//char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
//writeJPEGBFile(pBuffer, filename);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}
My question is what am I doing wrong and how can I pass the rawData pointer to the writeJPEGBFile() function successfully in the main() function?
The definition for scanGetFrame() is as follows:
typedef void *FTR_PVOID;
FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetFrame( FTRHANDLE ftrHandle, FTR_PVOID pBuffer, PFTRSCAN_FRAME_PARAMETERS pFrameParameters );
The scanGetFrame() function comes from a 3rd party library that I am linking with so I will not be able to change the definition.
Given that rawData is a null pointer in main(), you almost certainly need to revise the interface to getRawImage() so that it takes a char ** and you pass &rawData to it. You also need to think about how the calling code will know how big the data is.
I managed to work it out. Thanks to all for the pointers which led me to the solution:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData; // Removed the NULL assignment
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
// Set the size of rawData - loadImageSize() sets the value of the ImageSize class variable.
loadImageSize();
rawData = (unsigned char *) malloc(ImageSize.nImageSize);
getRawImage(rawData);
// This works now
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}

Segmentation fault with arrays and pointers

I have a segmentation fault...i'm not sure what's causing it. Also, when passing the member pname into the function get_names, am I doing this correctly, or is there a better way of doing this?
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str);
int main (void) {
int i;
for (i = 0; i < MAX_PLAYRS; i++) {
get_names(i, &(*player[i].pname));
printf("Player: %s\n", player[i].pname);
}
}
void get_names (int count, char *str) {
FILE *inp;
char status;
inp = fopen("teamnames.rtf", "r");
status = fscanf(inp, "%s", str);
if (status == EOF) {
count = MAX_PLAYRS;
}
}
With your code unchanged, I get a segmentation fault if the file can't be opened properly (i.e. it's unreadable due to permissions, or it simply does not exist).
Here's a modified version of you function get_names():
void get_names(int count, char *str)
{
FILE *inp;
inp = fopen("teamnames.rtf", "r");
if (inp == NULL) {
perror("Failed");
return;
}
fgets(str, MAX_NAME, inp);
fclose(inp);
}
This would still read the first name 16 times, but it would tell you why it didn't manage to open the file. To read the next name from the file (rather than repeatedly the first name), open (and close) the file in the main() function instead.
Also, you might as well call get_names() like so:
get_names(i, player[i].pname);
No need to do that &(*...) thing you're doing.
And, finally, I hope that the teamnames.rtf file is not actually an RTF file, but a simple text file with a name on each line.
The problem comes from this line:
get_names(i, &(*player[i].pname));
Understanding pointers and dereferencing is one of the biggest adjustments to learning C if you are switching from another language. You're doing it wrong, and I think you should seek out a tutorial on the subject. Try http://www.cplusplus.com/doc/tutorial/pointers/ as a starting point.
Get a debugger to tell you what is wrong. Compile the code with debugging enabled (see you man page for your compiler) and run something like this:
gdb a.out core
Then you should be able to see which line made the code core dump. You could use idb as well, if you have the intle compiler installed. This is, of course, on *nix. If you are talking windows, use the VS debugger.
In addition do NOT use fscanf as it is unsafe. Use fgets instead.
There are many strange things. First thing is, it seems like the names are in a file, but what you are doing is in every iteration of your for loop, you call get_names which opens the file again, that is goes to the beginning of the file and you read the same name over and over again.
That is if you closed the file. Since you haven't closed the file, the file is already open and you keep reopening it (which could be the cause of your problem)
Another thing is, how can
if (status == EOF) {
count = MAX_PLAYRS;
}
Give you the current count? Regardless of the count of the players in the file, you are just setting it to MAX_PLAYERS.
Another thing is that count is an input to the function that is not a pointer, so setting it does not change the value outside the function (which is what I assumed you wanted).
Here is how I would do it with minimum change to your code:
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str, FILE *inp);
int main (void) {
FILE *inp;
int i;
int count;
inp = fopen("teamnames.rtf", "r");
for (i = 0; i < MAX_PLAYRS; i++) {
get_names(&count, player[i].pname, inp);
printf("Player: %s\n", player[i].pname);
}
}
void get_names (int *count, char *str) {
char status;
status = fscanf(inp, "%s", str);
if (status == EOF) {
*count = MAX_PLAYRS;
}
}
Here is how I would do it more concisely:
#include <stdio.h>
#define MAX_NAME 20
#define MAX_PLAYRS 16
typedef struct {
char pname[MAX_NAME];
int runs;
char how_out;
} Team_t;
Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
int get_names (Team_t *team);
int main (void) {
get_names(player);
}
int get_names (Team_t *team) {
int i = 0;
FILE *inp;
inp = fopen("teamnames.rtf", "r");
while (i < MAX_PLAYRS && !feof(inp) {
fscanf(inp, "%s", team[i].pname);
printf("Player: %s\n", player[i].pname);
}
}
Note that the problems with fscanf, checking array boundaries etc are not the concern of this solution, but this rather gives you the idea of what to do not a code for you to copy-paste.

I get segmentation fault reading infoheader on a BMP using fread. How do I fix this please?

This is got me pretty stuck, how do I fix this? I know I haven't got error checking, but they aren't required i'd guess since it's restricted to my desktop. It obveously can't be EOF. It's for the infoheader struct, fileheader works fine. Do i need to take a new line or something?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize;
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
}FILEHEADER;
typedef struct
{
unsigned int biSize;
int width; /* Width of the image */
int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}INFOHEADER;
typedef struct
{
unsigned char b; /* Blue value */
unsigned char g; /* Green value */
unsigned char r; /* Red value */
}IMAGECOMPONENT;
int fileheadfunc(FILE *image);
int infoheadfunc(FILE *image);
int main( int argc, char *argv[] )
{
char *filename; /* *threshholdInput = argv[2]; */
FILE *image;
int filehead, infohead;
filename = argv[1];
/* int threshhold = atoi(threshholdInput); */
if (argc != 2)
{
printf(" Incorrect Number Of Command Line Arguments\n");
return(0);
}
image = fopen( filename, "r");
if (image == NULL)
{
fprintf(stderr, "Error, cannot find file %s\n", filename);
exit(1);
}
filehead = fileheadfunc(image);
infohead = infoheadfunc(image);
fclose(image);
return(0);
}
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek (image , 0 , SEEK_SET);
fread( (unsigned char*)header, sizeof(FILEHEADER), 1, image );
if ( (*header).fileMarker1 != 'B' || (*header).fileMarker2 != 'M' )
{
fprintf(stderr, "Incorrect file format");
exit(1);
}
printf("This is a bitmap!\n");
pos = ftell(image);
printf("%ld\n", pos);
printf("%zu\n", sizeof(FILEHEADER));
return(0);
}
int infoheadfunc(FILE *image)
{
INFOHEADER *iheader;
fseek (image, 0, SEEK_CUR );
fread( (unsigned int*)iheader, sizeof(INFOHEADER), 1, image );
printf("Width: %i\n", (*iheader).width);
printf("Height: %i\n", (*iheader).height);
return(0);
}
You're not actually allocating any storage for the BMP header data structures, e.g. you need to change this:
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek(image, 0, SEEK_SET);
fread((unsigned char*)header, sizeof(FILEHEADER), 1, image);
...
to this:
int fileheadfunc(FILE *image)
{
FILEHEADER header; // <<<
long pos;
fseek(image, 0, SEEK_SET);
fread(&header, sizeof(FILEHEADER), 1, image); // <<<
...
Also, as previously noted in one of the comments above, you need #pragma pack(1) (or equivalent if you're not using gcc or a gcc-compatible compiler) prior to your struct definitions to eliminate unwanted padding. (NB: use #pragma pack() after your struct definitions to restore normal struct padding/alignment.)
There are two problems with the code:
Alignment
For performance reasons the compiler will, unless instructed to do otherwise, arrange struct fields on its "natural boundaries", effectively leaving uninitialised gaps between byte-size fields. Add
#pragma pack(1)
before the struct definitions and you should be fine. It's also easy to test: just print out the struct size without and with pragma pack in place, and you'll see the difference.
Allocation
As Paul R already said, you should allocate space for the headers, not just provide a pointer to the structures. The fact that fileheadfunc works is a coincidence, there just wasn't anything in the way that got smashed when data got written outside of the allocated space.
A last one, just for prevention sake: should you ever want to return the read structures to the calling program, do not just return a pointer to the structure allocated in the function as that will cause problems similat to the unallocated variables you have now. Allocate them in the calling function, and pass a pointer to that variable to the header read functions.
EDIT clarification regarding the last point:
DON'T
FILEHEADER * fileheadfunc(FILE *image)
{
FILEHEADER header;
...
return &header; // returns an address on the function stack that will
// disappear once you return
}
DO
int fileheadfunc(FILE *image, FILEHEADER *header)
{
...
}
which will be called like this
...
FILEHEADER header;
returnvalue = fileheaderfunc(imagefile,&header);
EDIT2: just noticed that the way you read the DIB header is not correct. There are several variations of that header, with different sizes. So after reading the file header you first need to read 4 bytes into an unsigned int and based on the value read select the correct DIB header structure to use (don't forget you already read its first field!) or tell the user you encountered an unsupported file format.

Resources