Thread: strcat - cannot convert char to const char

  1. #1
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582

    strcat - cannot convert char to const char

    I use Visual C++ 2005 Express to make programs with, and I'm generally rather new to C programming although, from another tool, I've known the basic syntax style for a long time. I'm trying to learn how to read and write files to automate a process I do with a hex edittor that is rather boring, time consuming, and prone to mistakes. I have two major issues, the big one being the "cannot convert char to const char" error involving strcat. Because I don't know how to convert an integer into a string without utilizing the number system, I figured I could just split the number into the digits 0 to 9 then add 48 to get the cooresponding digit character. I then thought of using strcat to stitch together these numbers to form the output, a file name (and path) in my case. This is where I'm stumped.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    double sample_rate_base; // temporary for getting the fractional parts for rounding - 7 significant figures isn't quite enough given that sample rates go to 400,000
    unsigned int sample_rate; // integerical rounded value of the above variable
    signed short loop_position; // loop position for the creation of files
    signed short loop_start; // starting point of the loop
    signed short loop_end; // the point where the loop will end
    unsigned int bytes_per_second; // equal to sample_rate*multiplier
    char multiplier; // the multiplier used for the bytes_per_second variable
    char file_head_start[24]; // for copying identical file header data
    char file_head_end[7]; // for copying the last parts of the file header data
    unsigned int file_length; // the length of the file after the header data in bytes
    char file_contents[]; // the contents of the file for copying, since the samples themselves don't change at all
    char file_name[]; // the file name for the output file
    
    FILE *file_pointer;
    
    void find_next_sample_rate()
    {
    	// Based on the new 48-step speed system
    	if (loop_position < -72)
    	{
    		sample_rate_base += (208.0+(1.0/3.0)); // 208 1/3
    	}
    
    	if (loop_position == -72)
    	{
    		sample_rate_base = 17500.0; // a special case to prevent rounding flaws from the float - I may need the double
    	}
    	
    	if ((loop_position > -72) && (loop_position <= -48))
    	{
    		sample_rate_base += 312.5;
    	}
    	
    	if ((loop_position > -48) && (loop_position <= -24))
    	{
    		sample_rate_base += (416.0+(2.0/3.0)); // 416 2/3
    	}
    	
    	if ((loop_position > -24) && (loop_position <= 0))
    	{
    		sample_rate_base += 625.0;
    	}
    	
    	if ((loop_position > 0) && (loop_position <= 24))
    	{
    		sample_rate_base += (833.0+(1.0/3.0)); // 833 1/3
    	}
    	
    	if ((loop_position > 24) && (loop_position <= 48))
    	{
    		sample_rate_base += 1250.0;
    	}
    	
    	if ((loop_position > 48) && (loop_position <= 72))
    	{
    		sample_rate_base += (1666.0+(2.0/3.0)); // 1666 2/3
    	}
    	
    	if ((loop_position > 72) && (loop_position <= 96))
    	{
    		sample_rate_base += 2500.0;
    	}
    	
    	if ((loop_position > 96) && (loop_position <= 120))
    	{
    		sample_rate_base += (3333.0+(1.0/3.0)); // 3333 1/3
    	}
    	
    	if (loop_position > 120)
    	{
    		sample_rate_base += 5000.0;
    	}
    	
    	loop_position += 1; // advance the loop position
    	sample_rate = (int)(sample_rate_base+0.5); // use starting value first and round it off
    	bytes_per_second = sample_rate*multiplier;
    }
    
    void get_new_file_name()
    {
    	// chars 48 through 57 are the numbers
    	char digit_1;
    	char digit_10;
    	char digit_100;
    	char digit_1000;
    	char digit_10000;
    	char digit_100000;
    	int remaining_part;
    	
    	digit_100000 = sample_rate/100000; // since integers are used, and junk after the decimal is ignored, only a single digit is present - breaks up numbers from 12500 to 400000 into digits
    	remaining_part = sample_rate-(100000*digit_100000); // gets rid of the 100,000's digit leaving 5 digits left
    	digit_100000 += 48; // shifts the digit value into the cooresponding character on the character map since 48 through 57 (decimal) are the digits
    	digit_10000 = remaining_part/10000; // continue splitting the number into the separate digits
    	remaining_part -= (10000*digit_10000);
    	digit_10000 += 48;
    	digit_1000 = remaining_part/1000;
    	remaining_part -= (1000*digit_1000);
    	digit_1000 += 48;
    	digit_100 = remaining_part/100;
    	remaining_part -= (100*digit_100);
    	digit_100 += 48;
    	digit_10 = remaining_part/10;
    	remaining_part -= (10*digit_10);
    	digit_10 += 48;
    	digit_1 = remaining_part;
    	digit_1 += 48;
    	
    	digit_100000 = (const char)digit_100000; // random test
    	strcpy(file_name, "C:\\My Documents\\Songs for MP3\\Desert Zone\\");
    	
    	if (loop_end >= 48) // if the highest possible is 100,000 or greater, add a sixth digit
    	{
    		strcat(file_name, digit_100000); // a special case - write only if base sample rate is 6 or more digits but write the leading 0
    	}
    	
    	strcat(file_name, digit_10000); // add the main common digits to the file name that are always present
    	strcat(file_name, digit_1000);
    	strcat(file_name, digit_100);
    	strcat(file_name, digit_10);
    	strcat(file_name, digit_1);
    	strcat(file_name, " Desert Zone.wav\0"); // add the space at the end with the null character terminating the string
    }
    
    void create_output_files()
    {
    	/*
    	notes about loop ranges (based of of the spreadsheet document):
    	-96, 12500 Hz
    	-84, 15000 Hz
    	-72, 17500 Hz
    	-64, 20000 Hz (extended minimum 50K)
    	-56, 22500 Hz (rarely used)
    	-48, 25000 Hz (standard minimum 50K)
    	-36, 30000 Hz (100K)
    	-24, 35000 Hz (100K)
    	-16, 40000 Hz (extended minimum 100K)
    	 -8, 45000 Hz (100K)
    	  0, 50000 Hz (standard minimum 100K)
    	 15, 62500 Hz (standard maximum 50K)
    	 24, 70000 Hz (extended maximum 50K)
    	 32, 80000 Hz (50K)
    	 40, 90000 Hz (50K)
    	 48, 100000 Hz (50K)
    	 63, 125000 Hz (standard maximum 100K)
    	 72, 140000 Hz (extended maximum 100K)
    	 80, 160000 Hz
    	 88, 180000 Hz
    	 96, 200000 Hz
    	108, 240000 Hz
    	120, 280000 Hz
    	128, 320000 Hz
    	136, 360000 Hz
    	144, 400000 Hz
    	*/
    
    	// first, set the range using the chart commented out above
    	
    	char temp_var;
    	
    	loop_start = -48; // starting point
    	loop_end = 15; // ending point
    	loop_position = loop_start; // start at the loop starting point
    	sample_rate = 25000; // copy sample rate from chart above with loop_position as the value to take from
    	bytes_per_second = sample_rate*multiplier;
    	
    	while(loop_position <= loop_end) // should create 64 files
    	{
    		printf("Current progress:  %d Hz, %d of %d processed\n", sample_rate, loop_position-loop_start, loop_end-loop_start);
    		scanf("%d", &temp_var); // to stop input to see results for testing
    		get_new_file_name(); // get the strings stitched together for the output file name
    		/*
    		file_pointer = fopen(file_name, "wb"); // open the file for writing in binary mode (WAV files are binary)
    		fwrite(file_head_start, 1, 24, file_pointer); // write the details in the same order as it was read in
    		fwrite(sample_rate, 4, 1, file_pointer);
    		fwrite(bytes_per_second, 4, 1, file_pointer);
    		fwrite(multiplier, 1, 1, file_pointer);
    		fwrite(file_head_end, 1, 7, file_pointer);
    		fwrite(file_length, 4, 1, file_pointer);
    		fwrite(file_contents, 1, file_length, file_pointer); // copies all the rest of the data, the samples themselves
    		fclose(file_pointer); // close the file to reuse the pointer (or is it handle as with Gamestudio?)
    		*/
    		
    		loop_position += 1; // increment the loop for another round
    		find_next_sample_rate();
    	}
    }
    
    void read_base_file()
    {
    	// this copies the full structure of the WAV file, since only 8 bytes are changed out of several million
    	/*
    	file_pointer = fopen("C:\\My Documents\\Songs for MP3\\Desert Zone\\Desert Zone base.wav", "rb"); // assign a pointer (or handle?) for handling the file
    	fread(file_head_start, 1, 24, file_pointer); // read into file_head_start in one-byte chunks and fill the array of 24 elements with the given file pointer
    	fread(sample_rate, 4, 1, file_pointer); // same as above but read a 4-byte chunk once instead
    	fread(bytes_per_second, 4, 1, file_pointer); // same as above
    	fread(multiplier, 1, 1, file_pointer); // read a one-byte chunk once instead of the above
    	fread(file_head_end, 1, 7, file_pointer); // read a one-byte chunk 7 times to fill the file header data's end
    	fread(file_length, 4, 1, file_pointer); // read the file length data value, the number of bytes after the head
    	fread(file_contents, 1, file_length, file_pointer); // read one-byte chunks for the entire file's length, which is the end of the file
    	fclose(file_pointer); // close the file
    	*/
    	
    	create_output_files(); // initiate the loop for creating the output files copying the data above changing the 8 bytes as needed
    }
    
    int main()
    {
    	read_base_file();
    }
    The get_new_file_name() function is where the errors are occurring due to strcat. strcpy works just fine (no errors nor warnings), but it's the part of stitching the numbers from the process above it together to form the end result.

    The file-related instructions are commented out as I first want to test to see if the other parts work as they should. Once I finish that, fixing any bugs, I'd then test the file inputs.

    What I'm trying to do is generate several WAV files with only the "sample rate" and "bytes per second" values changed (as to change the speed without any degradation; a mere 8 bytes). I currently do this using a hex edittor and I don't have any problems with that (as the results play back without any trouble). Only 8 bytes in the entire file get changed. The sample rate varies from 12500 Hz to as high as 400,000 Hz at the extreme ends, both of which play back just fine. Since only 8 bytes change, I figure it'd be better to just load the contents of the base file into memory (the source) then write the outputs with only the 8 bytes changed accordingly. The second thing I'm concerned about is whether or not I used the file instructions properly. That is, when a file is opened, it starts at the first byte of the file and after each read or write instruction, it advances accordingly. That is, if 24 bytes were read followed by an instruction to read a group of 4 bytes, it would read at the 25th byte rather than go back to the first byte. The file is closed to allow for reusing the handle or pointer (not sure which it is - it's a handle in my other tool I used which is very limited) for another file. The code should generate 64 WAV files of the same file size as the source, a bit over 46 MB.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > get_new_file_name
    Seems an awfully long winded way of doing
    Code:
    sprintf( file_name,
             "C:\\My Documents\\Songs for MP3\\Desert Zone\\%06d\\Desert Zone.wav"
             sample_rate );
    > // add the space at the end with the null character terminating the string
    String constants always have a \0 at the end, you're just wasting effort adding another one.


    > char file_contents[]; // the contents of the file for copying, since the samples themselves don't change at all
    > char file_name[]; // the file name for the output file
    You need to allocate space yourself.
    The compiler won't magically work out how much space you need.

    Also, why are there so many global variables and so few parameters?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    strcat expects a string (char*) and you're passing it a single character (char).

    You can use sprintf(), or manipulate the string directly, setting the NULL to the new character and shifting the NULL the the next character.

    Code:
    	if ((loop_position > -72) && (loop_position <= -48))
    	{
    		sample_rate_base += 312.5;
    	}
    	
    	if ((loop_position > -48) && (loop_position <= -24))
    	{
    		sample_rate_base += (416.0+(2.0/3.0)); // 416 2/3
    	}
    	
    	if ((loop_position > -24) && (loop_position <= 0))
    	{
    		sample_rate_base += 625.0;
    	}
    You could write that much more concisely with else if statements.

    Code:
    char file_name[]; // the file name for the output file
    You probably want a size in there.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Quote Originally Posted by Salem
    > get_new_file_name
    Seems an awfully long winded way of doing
    Code:
    sprintf( file_name,
             "C:\\My Documents\\Songs for MP3\\Desert Zone\\%06d\\Desert Zone.wav"
             sample_rate );
    The only reason I did all that was because I didn't know of any other method (I didn't know of the sprintf function).

    > // add the space at the end with the null character terminating the string
    String constants always have a \0 at the end, you're just wasting effort adding another one.

    I wasn't too sure on this so I added it just to be safe (since the null terminating character is extremely important).

    > char file_contents[]; // the contents of the file for copying, since the samples themselves don't change at all
    > char file_name[]; // the file name for the output file
    You need to allocate space yourself.
    The compiler won't magically work out how much space you need.

    Also, why are there so many global variables and so few parameters?
    Because the file sizes vary a lot (from barely 1 MB to nearly 700 MB at the extreme high end), having to right-click on every base WAV file in Windows Explorer to view the file size and copy it is a bit ridiculous. With the 94,172,862-byte base file, about in my typical size range, an array with 100,000,000 items just wastes a lot of space, even if I went with 95 MB.

    The reason for all the global variables is that I know they are faster to use and there are many of them that get changed in the functions that others use. The whole thing is otherwise an entire loop. The "get_new_file_name" function is used with the "create_output_files" function. The "find_next_sample_rate" function is also used within the "create_output_files" function. By separating these separate tasks, it helps organize things better. This is only for my home use to help automate a rather boring task and thus optimization and speed really aren't all that important. Thanks though for the assistance. I'm still used of the numerous limitations of my old tool, the reason for going with C. Using else if is one of those limitations I'm used to so I'm used of just using a long series of if statements without any else used. There's so much new stuff with C that I'm not used to and it would take a while to break away from the habits I've developed with the old tool I've used for about a year.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    And saying char array[ ]; is typically 0 bytes - not so good is it?

    Anyway, even with very large files, there is seldom any need to store the WHOLE thing in memory at one go.

    Even if you do, there is such a thing as finding out the size of the file, then allocating memory to match the file size.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Well, I fixed a few of the bugs I had without the file stuff, but now I've got another problem very related to the original. In the "read_base_file" function at the bottom, I uncommented the file-related instructions to check to see if they work. The build log gives a rather bizarre set of errors, almost randomly chosen. I get this:

    ------ Build started: Project: WAV file sample rate generator, Configuration: Debug Win32 ------
    Compiling...
    WAV file sample rate generator.cpp
    .\WAV file sample rate generator.cpp(131) : warning C4996: 'sprintf' was declared deprecated
    C:\Program Files\Microsoft Visual Studio 8\VC\include\stdio.h(345) : see declaration of 'sprintf'
    Message: 'This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
    .\WAV file sample rate generator.cpp(136) : warning C4996: 'sprintf' was declared deprecated
    C:\Program Files\Microsoft Visual Studio 8\VC\include\stdio.h(345) : see declaration of 'sprintf'
    Message: 'This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
    .\WAV file sample rate generator.cpp(140) : warning C4996: 'scanf' was declared deprecated
    C:\Program Files\Microsoft Visual Studio 8\VC\include\stdio.h(295) : see declaration of 'scanf'
    Message: 'This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
    .\WAV file sample rate generator.cpp(161) : warning C4996: 'fopen' was declared deprecated
    C:\Program Files\Microsoft Visual Studio 8\VC\include\stdio.h(234) : see declaration of 'fopen'
    Message: 'This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
    .\WAV file sample rate generator.cpp(163) : error C2664: 'fread' : cannot convert parameter 1 from 'unsigned int' to 'void *'
    Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
    .\WAV file sample rate generator.cpp(164) : error C2664: 'fread' : cannot convert parameter 1 from 'unsigned int' to 'void *'
    Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
    .\WAV file sample rate generator.cpp(165) : error C2664: 'fread' : cannot convert parameter 1 from 'char' to 'void *'
    Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
    .\WAV file sample rate generator.cpp(167) : error C2664: 'fread' : cannot convert parameter 1 from 'unsigned int' to 'void *'
    Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
    Build log was saved at "file://c:\My Documents\My programs\WAV file sample rate generator\WAV file sample rate generator\Debug\BuildLog.htm"
    WAV file sample rate generator - 4 error(s), 4 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
    Line 161 is where the fopen instruction is. The line below it (162), strangely enough, does not have any problems. Lines 163 through 165 produce errors. Line 166 is just fine (no errors) 167 is errored and 168 is also just fine. The fclose instruction works just fine. Why the randomness and the errors? The variables sample_rate and bytes_per_second are both 32-bit integers. I'm confused about this.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > WAV file sample rate generator.cpp
    You're compiling your C program with a C++ compiler.

    Rename it to be a .c file.

    > _CRT_SECURE_NO_DEPRECATE
    In the project settings for the compiler, under the preprocessor section, you should be able to define your own conditional compilation flags. Add this flag to that list

    Alternatively, this on the very first line, before any includes should also work
    Code:
    #define _CRT_SECURE_NO_DEPRECATE
    > .\WAV file sample rate generator.cpp(163) : error C2664: 'fread' : cannot convert parameter 1 from 'unsigned int' to 'void *'
    Things like this
    fread(sample_rate, 4, 1, file_pointer);
    Need to be like this
    fread( &sample_rate, 4, 1, file_pointer);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Note also that your read procedure is not compatible with the wave file format
    There are no restrictions upon the order of the chunks within a WAVE file, with the exception that the Format chunk must precede the Data chunk. Some inflexibly written programs expect the Format chunk as the first chunk (after the RIFF header) although they shouldn't because the specification doesn't require this.
    Read this http://www.borg.com/~jglatt/tech/wave.htm
    You should always start with reading the chunk format and size
    when analyze format tag and deceide if you want to skip size bytes or parse them
    header size can be different depending on the compression used - so you should avoid code like
    Code:
    fread(file_head_end, 1, 7, file_pointer); // read a one-byte chunk 7 times to fill the file header data's end
    that uses magical numbers... they will be correct with only several files, with others your code will fail
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Quote Originally Posted by vart
    Note also that your read procedure is not compatible with the wave file format


    Read this http://www.borg.com/~jglatt/tech/wave.htm
    You should always start with reading the chunk format and size
    when analyze format tag and deceide if you want to skip size bytes or parse them
    header size can be different depending on the compression used - so you should avoid code like
    Code:
    fread(file_head_end, 1, 7, file_pointer); // read a one-byte chunk 7 times to fill the file header data's end
    that uses magical numbers... they will be correct with only several files, with others your code will fail
    The reason why I did it that way was because I'm merely copying files with only 8 bytes changed. To help understand:

    The first 24 bytes are the same in every file within the group. The next 4 bytes, the sample rate, is different for each file. With the sample rate changing, the "bytes per second" value, the next 4 bytes after it, also change, of which is multiplied by the value in the next byte after this, the reason for reading that separate, since it doesn't change. The next 7 bytes after this are merely copied with the next 4 being the length of the data part of the file, of which is the file size minus 44 (44 bytes is how big the header data is). For file to be copied properly, I need this value and thus it is read separately. The last of the data, the samples, are merely just copied as is.

    When the output files are written, the first 24 bytes are written since they never change. The sample rate is then changed according to the little piece of code to find the resulting value (which then converts it to an integer and rounds it to the nearest whole number to provide maximum possible precision). Since the bytes per second value is the result of sample_rate*multiplier, this value is set based on that. The multiplier is usually 2 since I work with 16-bit mono files, but sometimes 24-bit mono giving a multiplier of 3. The multiplier value is copied from what was read in the source file since it never changes and the 7 bytes after that are also copied since they don't change. The file length never changes either and thus is copied as well as all the file data after it. The loop starts again with the same thing happening only a different sample rate and "bytes per second" value are used.

    Just to give you an idea, here's a screenshot I took quite a while ago that shows you what data I use. Unlike the third highlighted value, the "bit depth" as shown in the screenshot, I use the multiplier value read directly after the "bytes per second" value, highlighted in red. The sample rate is highlighted in blue. The 24 bytes to the left are not changed in each file and are merely copied. Everything else after the "bytes per second" value is also copied without modification. Just the blue and red highlighted areas are changed in each file, a mere 8 bytes. By changing these 8 bytes in the hex edittor and playing the change in any audio player (Winamp in my case), it plays back just as I expected. If I change the sample rate from 48,000 Hz to 40,000 Hz, the file would be 20% longer with the pitch 5/6 that of what it was (instead of 1200 Hz, it plays as 1000 Hz). If I later change it again to 32,000 Hz, it would play back even slower with an even lower pitch (1200 Hz would be 800 Hz and would play 50% longer than the original 48,000 Hz).

    Edit: making the change to a .c file instead of .cpp, it now compiles without any errors, but the program doesn't run at all like it was and the warnings show something weird with lines 163, 164, 165, and 167, those same ones giving the errors in my previous case. The build log shows this for the relavent area.

    .\WAV file sample rate generator.c(163) : warning C4022: 'fread' : pointer mismatch for actual parameter 1
    .\WAV file sample rate generator.c(164) : warning C4022: 'fread' : pointer mismatch for actual parameter 1
    .\WAV file sample rate generator.c(165) : warning C4022: 'fread' : pointer mismatch for actual parameter 1
    .\WAV file sample rate generator.c(167) : warning C4022: 'fread' : pointer mismatch for actual parameter 1
    Pointer mismatch? This doesn't make sense as it works just fine with other fread instructions in the same group. What's so special about lines 162, 166, and 168 that don't cause problems whereas the other lines in the same group with the same instructions used do? That's probably why it couldn't compile it as a C++ file.

    In the debug dialog, I get this at the end:

    The program '[3956] WAV file sample rate generator.exe: Native' has exited with code -1073741811 (0xc000000d).
    What does this mean?
    Last edited by ulillillia; 12-07-2006 at 03:01 AM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > The program '[3956] WAV file sample rate generator.exe: Native' has exited with code -1073741811 (0xc000000d).
    It means your int main doesn't have a return 0; at the end. So the actual return value just happens to be whatever happened to be lying around in some register or other.
    C++ will assume this is what you meant, C does not.

    > .\WAV file sample rate generator.c(163) : warning C4022: 'fread' : pointer mismatch for actual parameter 1
    Seems odd - can you post your latest code please.

    Some older compilers assume fread() takes a char* as the first parameter rather than a void* (as required by ANSI-C).
    This obviously works fine if what you're reading into is in fact a char array.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Okay, so I added the "return(0);" at the end of the main function. Oddly enough, I didn't get any errors as it does with any other function.

    I don't think "Visual C++ 2005 Express", the program I use to write and compile programs with, is an old compiler. Afterall, I downloaded it from Microsoft's website about 2 or 3 weeks ago.

    You wanted the updated code so here it is:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    double sample_rate_base; // temporary for getting the fractional parts for rounding - 7 significant figures isn't quite enough given that sample rates go to 400,000
    unsigned int sample_rate; // integerical rounded value of the above variable
    signed short loop_position; // loop position for the creation of files
    signed short loop_start; // starting point of the loop
    signed short loop_end; // the point where the loop will end
    unsigned int bytes_per_second; // equal to sample_rate*multiplier
    char multiplier; // the multiplier used for the bytes_per_second variable
    char file_head_start[24]; // for copying identical file header data
    char file_head_end[7]; // for copying the last parts of the file header data
    unsigned int file_length; // the length of the file after the header data in bytes
    char file_contents[95000000]; // the contents of the file for copying, since the samples themselves don't change at all // use array with size bigger than file size
    char file_name[128]; // the file name for the output file
    
    FILE *file_pointer;
    
    void find_next_sample_rate()
    {
    	// Based on the new 48-step speed system
    	if (loop_position < -72)
    	{
    		sample_rate_base += (208.0+(1.0/3.0)); // 208 1/3
    	}
    	
    	else if (loop_position == -72)
    	{
    		sample_rate_base = 17500.0; // a special case to prevent rounding flaws from the double
    	}
    	
    	else if ((loop_position > -72) && (loop_position <= -48))
    	{
    		sample_rate_base += 312.5;
    	}
    	
    	else if ((loop_position > -48) && (loop_position <= -24))
    	{
    		sample_rate_base += (416.0+(2.0/3.0)); // 416 2/3
    	}
    	
    	else if ((loop_position > -24) && (loop_position <= 0))
    	{
    		sample_rate_base += 625.0;
    	}
    	
    	else if ((loop_position > 0) && (loop_position <= 24))
    	{
    		sample_rate_base += (833.0+(1.0/3.0)); // 833 1/3
    	}
    	
    	else if ((loop_position > 24) && (loop_position <= 48))
    	{
    		sample_rate_base += 1250.0;
    	}
    	
    	else if ((loop_position > 48) && (loop_position <= 72))
    	{
    		sample_rate_base += (1666.0+(2.0/3.0)); // 1666 2/3
    	}
    	
    	else if ((loop_position > 72) && (loop_position <= 96))
    	{
    		sample_rate_base += 2500.0;
    	}
    	
    	else if ((loop_position > 96) && (loop_position <= 120))
    	{
    		sample_rate_base += (3333.0+(1.0/3.0)); // 3333 1/3
    	}
    	
    	else // for beyond 120
    	{
    		sample_rate_base += 5000.0;
    	}
    	
    	sample_rate = (int)(sample_rate_base+0.5); // use starting value first and round it off
    	bytes_per_second = sample_rate*multiplier;
    }
    
    void create_output_files()
    {
    	/*
    	notes about loop ranges (based of of the spreadsheet document):
    	-96, 12500 Hz
    	-84, 15000 Hz
    	-72, 17500 Hz
    	-64, 20000 Hz (extended minimum 50K)
    	-56, 22500 Hz (rarely used)
    	-48, 25000 Hz (standard minimum 50K)
    	-36, 30000 Hz (100K)
    	-24, 35000 Hz (100K)
    	-16, 40000 Hz (extended minimum 100K)
    	 -8, 45000 Hz (100K)
    	  0, 50000 Hz (standard minimum 100K)
    	 15, 62500 Hz (standard maximum 50K)
    	 24, 70000 Hz (extended maximum 50K)
    	 32, 80000 Hz (50K)
    	 40, 90000 Hz (50K)
    	 48, 100000 Hz (50K)
    	 63, 125000 Hz (standard maximum 100K)
    	 72, 140000 Hz (extended maximum 100K)
    	 80, 160000 Hz
    	 88, 180000 Hz
    	 96, 200000 Hz
    	108, 240000 Hz
    	120, 280000 Hz
    	128, 320000 Hz
    	136, 360000 Hz
    	144, 400000 Hz
    	*/
    
    	// first, set the range using the chart commented out above
    	
    	char temp_var;
    	
    	loop_start = -48; // starting point
    	loop_end = 15; // ending point
    	loop_position = loop_start; // start at the loop starting point
    	sample_rate = 25000; // copy sample rate from chart above with loop_position as the value to take from
    	sample_rate_base = sample_rate;
    	bytes_per_second = sample_rate*multiplier;
    	
    	while(loop_position <= loop_end) // should create 64 files
    	{
    		printf("Current progress:  %d Hz, %d of %d processed\n", sample_rate, loop_position-loop_start, loop_end-loop_start+1); // temporary items for debugging purposes
    		printf("loop_position:  %d, multiplier:  %d, sr base:  %6.3f\n", loop_position, multiplier, sample_rate_base);
    		
    		if (loop_end >= 48) // if 6 figure sample rates are expected, a leading zero is needed to allow for the speeds to be sorted properly from slowest to fastest
    		{
    			sprintf(file_name, "C:\\My Documents\\Songs for MP3\\Desert Zone\\%06d Desert Zone.wav", sample_rate);
    		}
    		
    		else // if only 5-figure sample rates are expected, the value can be left as is
    		{
    			sprintf(file_name, "C:\\My Documents\\Songs for MP3\\Desert Zone\\%05d Desert Zone.wav", sample_rate);
    		}
    		
    		printf(file_name); // to make sure the file name is set properly, again for debugging reasons
    		scanf("%d", &temp_var); // to stop input to see results for testing
    		/*
    		file_pointer = fopen(file_name, "wb"); // open the file for writing in binary mode (WAV files are binary)
    		fwrite(file_head_start, 1, 24, file_pointer); // write the details in the same order as it was read in
    		fwrite(sample_rate, 4, 1, file_pointer);
    		fwrite(bytes_per_second, 4, 1, file_pointer);
    		fwrite(multiplier, 1, 1, file_pointer);
    		fwrite(file_head_end, 1, 7, file_pointer);
    		fwrite(file_length, 4, 1, file_pointer);
    		fwrite(file_contents, 1, file_length, file_pointer); // copies all the rest of the data, the samples themselves
    		fclose(file_pointer); // close the file to reuse the pointer (or is it handle as with Gamestudio?)
    		*/
    		
    		loop_position += 1; // increment the loop for another round
    		find_next_sample_rate();
    	}
    }
    
    int main()
    {
    	// this copies the full structure of the WAV file into memory for the output files later, since only 8 bytes are changed out of several million
    	file_pointer = fopen("C:\\My Documents\\Songs for MP3\\Desert Zone\\Desert Zone base.wav", "rb"); // assign a pointer (or handle?) for handling the file and read in binary mode
    	fread(file_head_start, 1, 24, file_pointer); // read into file_head_start in one-byte chunks and fill the array of 24 elements with the given file pointer
    	fread(sample_rate, 4, 1, file_pointer); // same as above but read a 4-byte chunk once instead
    	fread(bytes_per_second, 4, 1, file_pointer); // same as above
    	fread(multiplier, 1, 1, file_pointer); // read a one-byte chunk once instead of the above
    	fread(file_head_end, 1, 7, file_pointer); // read a one-byte chunk 7 times to fill the file header data's end
    	fread(file_length, 4, 1, file_pointer); // read the file length data value, the number of bytes after the head
    	fread(file_contents, 1, file_length, file_pointer); // read one-byte chunks for the entire file's length, which is the end of the file
    	fclose(file_pointer); // close the file
    	
    	create_output_files(); // initiate the loop for creating the output files copying the data above changing the 8 bytes as needed
    	return(0);
    }
    You may note a few changes, some of those mentioned in this thread being some. Before I uncommented the file reading lines, I tested things and fixed a few bugs I encountered.

    I also recompiled the program after the return(0); was added and I still get the same exit code value. By commenting out the file read instructions at the end, I get the message in the debug dialog saying:

    The program '[2392] WAV file sample rate generator.exe: Native' has exited with code -1073741510 (0xc000013a).
    The program ran successfully though and didn't abruptly close. There's something seriously wrong with the file instructions.

  12. #12
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    fread(sample_rate, 4, 1, file_pointer);
    should be
    fread(&sample_rate, 4, 1, file_pointer);

    the same for other non-array variables
    and check the file_length before reading into file_contents array
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  13. #13
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    I was using the example here at the bottom to do that but the ampersand was not there at the beginning which is why it didn't work like that. I made this fix and, although there was a two-second delay before I saw the printed details come up, I checked Windows Task Manager and saw that it read the 94-million some bytes I was expecting to see and thus I can tell it's working. I expected a delay of about that time span since that's about the typical maximum my hard drive can read and write at a sustained speed. It was just over 50,000 before this. I take it the write instructions also need this. Oh well, more testing. Thanks for the help .

  14. #14
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by ulillillia
    I was using the example here
    In this example x is an array, and it means it is an address of the first element.

    In your code there is no problem with arrays... But non arrays variable should be passed by pointer...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  15. #15
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Oh, I see now. Perhaps this detail could be added to that tutorial.

    Anyway, I've fixed the bugs and had it write the output files. The WAV files it wrote played back just fine and in the way I expected. With this program, I can process what I was doing with the hex edittor nearly ten times faster. Thank you for the assistance. I appreciate it. Now to bulk-convert all the resulting WAV files into MP3 - time for Audacity.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  2. Playing card data structure?
    By crypticgeek in forum C++ Programming
    Replies: 10
    Last Post: 12-31-2006, 05:29 PM
  3. fatal error LNK1104
    By DMH in forum C++ Programming
    Replies: 2
    Last Post: 11-16-2005, 03:46 AM
  4. comparing fields in a text file
    By darfader in forum C Programming
    Replies: 9
    Last Post: 08-22-2003, 08:21 AM
  5. AnsiString versus char *
    By Zahl in forum C++ Programming
    Replies: 35
    Last Post: 10-16-2002, 08:38 PM