iinf

iinf

  • NA
  • 19
  • 0

conversion from c to c#

Dec 3 2006 2:59 PM

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 byte
unsigned 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 buffer
void 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 bytes
void skip_bytes(int n) {
 for(; n; n--) {
    if(fgetc(wave) == EOF) error(invalid_format);
   }
}

// Reads dword
unsigned 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 word
short read_word(void) {
 read_bytes(2);
   return (short)(((unsigned char)in[1] << 8) | (unsigned char)in[0]);
}

// Formats sample index as time value
char *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 found
signed 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 stderr
void 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 filter
enum 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 question
enum 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 header
void 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 bytes
void write_bytes(const char *p, int count) {
 for(;count > 0; count--) {
    if(fputc((unsigned char)*p, out) == EOF) error(write_failed);
      p++;
   }
}

// Writes dword
void 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 word
void 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);
}