Can anyone please convert following c code into visual studio c# windows project, I will be very much thankful to him/her:/* Default values */#define FILTER 10#define THRESHOLD 0.05#define GAP 2.0
/* Limits */#define MAXFILTER 1000#define MAXSAMPLE 0x7FFF#define SAMPLERATE 44100U
/* Include files */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <limits.h>// For MAXPATH#include <dir.h>// For switching <stdin> to binary mode#include <io.h>#include <fcntl.h>
/* Constants */enum bool { false, true };enum err { invalid_format, not_found, too_long, no_tracks, write_failed, rewind_failed, truncate_failed, usage, interrupted, too_many_tracks};const char *const err[] = { "\nInvalid WAVE format. Must be 16-bit stereo 44100 Hz PCM.", "\nFile not found.", "\nToo long WAVE file.", "\nNo tracks detected in the WAVE file.", "\nCannot write new WAVE file.", "\nFailed to rewind back to the track start.", "\nFailed to remove the track from WAVE file.", "\nInvalid arguments.", "\nCancelled by user.", "\nToo many tracks."};const char riff[] = { 'R', 'I', 'F', 'F' };const char wavefmt[] = { 'W','A','V','E','f','m','t',' ', 0x10,0,0,0, 0x01,0,0x02,0, 0x44,0xAC,0,0, 0x10,0xB1,0x02,0, 0x04,0,0x10,0, 'd','a','t','a'};
/* Global variables */char in[4];FILE *wave, *out = NULL;unsigned long sample = 0, samples = 0;enum bool interactive = true, normalize = false, preserve = false;int filter = FILTER;unsigned long threshold = MAXSAMPLE * THRESHOLD;unsigned long gap = SAMPLERATE * GAP;long cut = -1;char infile[MAXPATH] = "", outfile[MAXPATH] = "", *outtrack;
/* Function prototypes */void read_parameter(int argc, char *argv[]);void error(enum err errno);unsigned long read_wave_header(void);void read_bytes(int n);void skip_bytes(int n);unsigned long read_dword(void);short read_word(void);char *timef(unsigned long u);void split_track(int track);void split_track_on_the_fly(int track);short find_track(int track, long *start, long *end);void show_progress(unsigned long u);enum bool update_filter(unsigned short *peak);enum bool ask(const char *question, enum bool value);void write_wave_header(int track, unsigned long samples);void write_bytes(const char *p, int count);void write_dword(unsigned long u);void write_word(signed short s);void truncate_file(const char *name, long pos);
/* Main */int main(int argc, char *argv[]) {
long dummy;
puts("\rFile data conversion"); read_parameter(argc, argv); // Check parameters if(!*outfile) strcpy(outfile, "TRACK"); if(cut < 0) cut = gap; if(!*infile || filter < 0 || filter > MAXFILTER || threshold <= 0 || threshold >= 0x7FFFU * 2 || gap <= 0 || cut < 0) error(usage);
// Show settings if(strcmp(infile, "-")) fprintf(stderr, "Input:\t%s\n", infile); else { fputs("Input:\t<stdin>\t(Splitting piped data \"on-the-fly\")\n", stderr); *infile = '\0'; } if(strcmp(outfile, "-")) fprintf(stderr, "Output:\t%sxx.WAV\n", outfile); else { fputs("Output file generation disabled (listing tracks only).\n", stderr); *outfile = '\0'; interactive = false; } fprintf(stderr, "Using detection threshold: %.3f (normalized)\n" "Using minimum gap duration: %.3f seconds\n" "Discarding track end: %.3f seconds\n" "Glitch removal filter: %d samples\n", (float)threshold / MAXSAMPLE, (float)gap / SAMPLERATE, (float)cut / SAMPLERATE, filter); // Final initialization of variables threshold *= (filter + 1); outtrack = strchr(outfile, '\0');
if(*infile) { wave = fopen(infile, "rb"); if(wave == NULL) error(not_found); } else { // Switch the <stdin> to binary mode setmode(fileno(stdin), O_BINARY); wave = stdin; } samples = read_wave_header() / 4; if(!samples) error(invalid_format); if(samples > LONG_MAX) error(too_long); fprintf(stderr, "\nEstimated WAVE data length %lu samples, %s\n" "Detecting track gaps...\n" "Track\tStart\t\tEnd\t\tLength\t\tPeak level\n", samples, timef(samples));
// Trim the beginning silence away if(find_track(0, &dummy, &dummy) >= 0) error(no_tracks); // Do the real splitting if(!*outfile || *infile) { split_track(1); fclose(wave); if(!preserve) unlink(infile); } else split_track_on_the_fly(1);
fputs("WAVE data successfully splitted. \n\a", stderr); return EXIT_SUCCESS;}
void read_parameter(int argc, char *argv[]) {
float f; char c;
if(argc < 2) return; if(argv[1][0] == '/') { // This is a switch if(argv[1][2] != '\0') error(usage); c = (char)toupper(argv[1][1]); switch(c) { case 'I': interactive = false; break; case 'N': normalize = true; break; case 'P': preserve = true; break; default: if(--argc < 2) error(usage); f = strtod(argv[2], NULL); switch(c) { case 'T': threshold = MAXSAMPLE * f; break; case 'G': gap = SAMPLERATE * f; break; case 'C': cut = SAMPLERATE * f; break; case 'F': filter = f; break; default: error(usage); } argv++; } } else { // This is a file name if(*infile) { if(*outfile) error(usage); strncpy(outfile, argv[1], MAXPATH - 7); } else strncpy(infile, argv[1], MAXPATH - 1); } argv++; argc--; // Recurse to read the next parametres read_parameter(argc, argv);}
void error(enum err errno) { if(errno == usage) puts( "WAVSPLIT [/I][/N][/P][/T thr][/G gap][/C cut][/F filt] infile [outbase]\n" "\n" "/I\tRuns without questions (non-interactive)\n" "/N\tNormalizes the volume of the tracks when used with /I\n" "/P\tPreserves original WAVE file (requires more disk space)\n" "/T thr\tSets the threshold of the track gap detection (normalized, 0...1),\n" "\tdefault 0.05\n" "/G gap\tSets the minimum length of the track gap (seconds), default 2.0\n" "/C cut\tDetermines the amount of the track end to discard (seconds),\n" "\tsame as /G by default\n" "/F filt\tSets the length of the filter for crack removal (samples, 0...1000),\n" "\tdefault 10\n" "infile\tThe original WAVE file (16-bit stereo 44100 Hz PCM),\n" "\tuse \"-\" for piped <stdin> input.\n" "outbase\tThe base name of the track file to generate, default \"TRACK\",\n" "\tuse \"-\" to disable output file generation (list tracks only)\n" "\n" "You need free disk space only for the largest individual track contained in the\n" "original WAVE file if the track files are generated on the same disk as the\n" "original and the /P switch is not specified.\n" "\n" "When using piped input, the file is split \"on-the-fly\" and normalization\n" "is not possible.\n" "\n" "Switches /I, /N, and /P have no effect with piped input or when output file\n" "generation is disabled."); fputs(err[errno], stderr); fputs("\n\a", stderr); fcloseall(); exit(EXIT_FAILURE);}
/* Other functions */// Returns number of PCM bytes and leaves file pointer at the first byteunsigned long read_wave_header(void) { read_bytes(4); if(strncmp("RIFF", in, 4)) return 0; skip_bytes(4); read_bytes(4); if(strncmp("WAVE", in, 4)) return 0; while(true) { read_bytes(4); if(!strncmp("fmt ", in, 4)) break; skip_bytes(read_dword()); } if(read_dword() != 16) return 0; // Must be PCM stereo if(read_dword() != 0x00020001UL) return 0; // Must be 44100 Hz if(read_dword() != SAMPLERATE) return 0; skip_bytes(6); // Must be 16-bit if(read_word() != 16) return 0; while(true) { read_bytes(4); if(!strncmp("data", in, 4)) break; skip_bytes(read_dword()); } return read_dword();}
// Reads n chars into buffervoid read_bytes(int n) {
char *p; int i;
for(p = in; p < in + n; p++) { i = fgetc(wave); if(i == EOF && samples) { fputs("\nUnexpected end of WAVE data.\n", stderr); // Clear the incorrect number of total samples samples = 0; } *p = (char)i; }}
// Discards n bytesvoid skip_bytes(int n) { for(; n; n--) { if(fgetc(wave) == EOF) error(invalid_format); }}
// Reads dwordunsigned long read_dword(void) {
unsigned long u; int i;
read_bytes(4); u = 0; for(i = 3; i >= 0; i--) { u = (u << 8) | (unsigned char)in[i]; } return u;}
// Reads wordshort read_word(void) { read_bytes(2); return (short)(((unsigned char)in[1] << 8) | (unsigned char)in[0]);}
// Formats sample index as time valuechar *timef(unsigned long u) {
static char buf[12];
sprintf(buf, "%2.2u:%2.2u.%3.3u", u / (60 * SAMPLERATE), (u / SAMPLERATE) % 60, ((u % SAMPLERATE) * 1000) / SAMPLERATE); return buf;}
// Finds the track gaps and then splits the file (recursive)void split_track(int track) {
long start, end, ptr; unsigned short peak;
if(track >= 100) error(too_many_tracks); // Store the file pointer ptr = ftell(wave) - filter * 4; // Detect the next track peak = find_track(track, &start, &end);
// Recurse to find the next track gap if(sample < samples) split_track(track + 1); else { if(!ask("\n\aSplit the file as shown above? (Y/N) ", true)) error(interrupted); normalize = ask("Normalize the track volume? (Y/N) ", normalize); } // Was it a null track (negative final length)? if(end <= start || !*outfile) return;
// Save the track as a new file fprintf(stderr, "Writing new WAVE file of track %u...\n", track); if(fseek(wave, ptr, SEEK_SET)) error(rewind_failed); write_wave_header(track, end - start); // Copy track data for(; start < end; start++) { show_progress(start); if(normalize) { write_word((short)(read_word() * (float)MAXSAMPLE / peak)); write_word((short)(read_word() * (float)MAXSAMPLE / peak)); } else write_dword(read_dword()); } if(fclose(out) == EOF) error(write_failed);
if(preserve || track == 1) return; // Truncate the original file fputs("Deleting the track from the WAVE file...\n", stderr); fclose(wave); truncate_file(infile, ptr); wave = fopen(infile, "rb"); if(wave == NULL) error(truncate_failed);}
// Splits the files "on-the-fly" (recursive)void split_track_on_the_fly(int track) {
long start, end;
if(track >= 100) error(too_many_tracks); // Create new track file write_wave_header(track, 0);
// Detect the next track find_track(track, &start, &end); // Write the length to the track file if(fseek(out, 4, SEEK_SET)) error(write_failed); write_dword((end - start) * 4 + 36); if(fseek(out, 40, SEEK_SET)) error(write_failed); write_dword((end - start) * 4); if(fclose(out) == EOF) error(write_failed);
// Cut the end as requested if(end <= start) unlink(outfile); else truncate_file(outfile, (end - start) * 4 + 44);
// Recurse to copy the next track if(sample < samples) split_track_on_the_fly(track + 1);}
// Finds the next track gap, returns the end of the track// When searching the first track (track = 0) returns negative if foundsigned short find_track(int track, long *start, long *end) {
long silence = 0; unsigned short peak = 0;
*start = sample - filter; if(*start < 0) *start = 0; while(sample < samples) { show_progress(sample); sample++; if(update_filter(&peak)) { if(!track) return -1; if(silence >= gap) break; silence = 0; } else silence++; } // In case of unexpected end, cut the extra "EOF sample" away *end = sample - filter - cut - (samples? 0 : 1); // Do not print results in case of null track if(*end > *start) { printf("\r%u\t%s\t", track, timef(*start)); printf("%s\t", timef(*end)); printf("%s\t%.3f\n", timef(*end - *start), (float)peak / MAXSAMPLE); } return peak;}
// Writes the current location to stderrvoid show_progress(unsigned long u) { if(u & 0x7FFF) return; fputs(timef(u), stderr); fputc('\r', stderr);}
// Reads new samples and filters the stream, returns true if there is enough// audio level in the filterenum bool update_filter(unsigned short *peak) {
static short filt_left[MAXFILTER] = { 0 }; static short filt_right[MAXFILTER] = { 0 }; static unsigned short index; unsigned short i; short left, right; unsigned long u;
left = filt_left[index]; right = filt_right[index]; if(sample > filter && out != NULL) { // If splitting "on-the-fly", write the overflowing data to the track file write_word(left); write_word(right); } left = (short)abs(left); right = (short)abs(right); if(*peak < left) *peak = left; if(*peak < right) *peak = right; // Read and save both channels filt_left[index] = read_word(); filt_right[index] = read_word();
if(++index > filter) index = 0;
u = 0; for(i = 0; i <= filter; i++) { left = (short)abs(filt_left[i]); right = (short)abs(filt_right[i]); if(left > right) u += left; else u += right; } return u > threshold;}
// Asks a questionenum bool ask(const char *question, enum bool value) { if(!interactive) return value; fputs(question, stderr); fflush(stdin); while(true) { switch(toupper(getchar())) { case 'Y': return true; case 'N': return false; } }}
// Creates a new WAVE file and writes the headervoid write_wave_header(int track, unsigned long samples) { sprintf(outtrack, "%2.2d.WAV", track); out = fopen(outfile, "wb"); if(out == NULL) error(write_failed); write_bytes(riff, 4); // Write file size write_dword(samples * 4 + 36); write_bytes(wavefmt, 32); // Write number of PCM data bytes write_dword(samples * 4);}
// Writes bytesvoid write_bytes(const char *p, int count) { for(;count > 0; count--) { if(fputc((unsigned char)*p, out) == EOF) error(write_failed); p++; }}
// Writes dwordvoid write_dword(unsigned long u) {
int i;
for(i = 0; i < 4; i++) { if(fputc((unsigned char)u, out) == EOF) error(write_failed); u >>= 8; }}
// Writes wordvoid write_word(signed short s) { if(fputc((unsigned char)s, out) == EOF || fputc((unsigned char)(s >> 8), out) == EOF) error(write_failed);}
// Removes the track from the original file#include <windows.h>void truncate_file(const char *name, long pos) {
HANDLE h; int b;
h = CreateFile(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(h == INVALID_HANDLE_VALUE) error(truncate_failed);
b = (SetFilePointer(h, pos, NULL, FILE_BEGIN) != pos || !SetEndOfFile(h)); b |= !CloseHandle(h); if(b) error(truncate_failed);}