public static double[][] BMPRead(BinaryFile bmpfile, ref int y, ref int x) { int iy = 0; // various iterators int ix = 0; int ic = 0; int offset = 0; double[][] image; byte zerobytes = new byte(); byte val = new byte(); #if DEBUG Console.Write("BMPRead...\n"); #endif if (GlobalMembersUtil.ReadUInt16(bmpfile) != 19778) // "BM" format tag check { Console.Error.WriteLine("This file is not in BMP format\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } bmpfile.Seek(8, SeekOrigin.Current); // skipping useless tags offset = (int)GlobalMembersUtil.ReadUInt32(bmpfile) - 54; // header offset bmpfile.Seek(4, SeekOrigin.Current); // skipping useless tags x = (int)GlobalMembersUtil.ReadUInt32(bmpfile); y = (int)GlobalMembersUtil.ReadUInt32(bmpfile); bmpfile.Seek(2, SeekOrigin.Current); // skipping useless tags if (GlobalMembersUtil.ReadUInt16(bmpfile) != 24) // Only format supported { Console.Error.WriteLine("Wrong BMP format, BMP images must be in 24-bit colour\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } bmpfile.Seek(24 + offset, SeekOrigin.Current); // skipping useless tags // image allocation image = new double[y][]; for (iy = 0; iy < y; iy++) { image[iy] = new double[x]; } zerobytes = (byte)(4 - ((x * 3) & 3)); if (zerobytes == 4) { zerobytes = 0; } for (iy = y - 1; iy != -1; iy--) // backwards reading { for (ix = 0; ix < x; ix++) { for (ic = 2; ic != -1; ic--) { val = bmpfile.ReadByte(); image[iy][ix] += (double)val * (1.0 / (255.0 * 3.0)); // Conversion to grey by averaging the three channels } } bmpfile.Seek(zerobytes, SeekOrigin.Current); // skipping padding bytes } bmpfile.Close(); return(image); }
public static void Main(string[] args) { /* * CommonUtils.FFT.FFTTesting.TimeSpectrograms(); * Console.ReadKey(); * return; * * int _channels = 0; * int _samplecount = 0; * int _samplerate = 0; * string _filenameIn = @"C:\Users\perivar.nerseth\Music\Sleep Away16.wav"; * string _filenameOut = @"C:\Users\perivar.nerseth\Music\Sleep Away16-test2.png"; * double[][] _sound = GlobalMembersSoundIO.ReadWaveFile(_filenameIn, ref _channels, ref _samplecount, ref _samplerate); // Sound input * double [] _s = _sound[0]; * * Spectrogram spectrogram = new Spectrogram(); * Bitmap bmp = spectrogram.to_image(ref _s, _samplerate); * bmp.Save(_filenameOut); * Console.ReadKey(); * return; * double[] out1 = new double[_samplecount]; * double[] out2 = new double[_samplecount]; * GlobalMembersDsp.FFT(ref _s, ref out1, _samplecount, GlobalMembersDsp.FFTMethod.DFT); * GlobalMembersDsp.FFT(ref out1, ref out2, _samplecount, GlobalMembersDsp.FFTMethod.IDFT); * * _sound[0] = out2; * * BinaryFile binOut = new BinaryFile(_filenameOut, BinaryFile.ByteOrder.LittleEndian, true); * GlobalMembersSoundIO.WriteWaveFile(binOut, _sound, 1, _samplecount, _samplerate, 16); * * Console.ReadKey(); * return; */ int argc = args.Length; BinaryFile fin; BinaryFile fout; int i = 0; double[][] sound; double[][] image; double basefreq = 0; double maxfreq = 0; double pixpersec = 0; double bpo = 0; double brightness = 1; int channels = 0; int samplecount = 0; int samplerate = 0; int Xsize = 0; int Ysize = 0; int format_param = 0; long clockb = 0; byte mode = 0; string in_name = null; string out_name = null; // initialisation of global using defaults defined in dsp.h GlobalMembersDsp.PI = PI_D; GlobalMembersDsp.LOGBASE = LOGBASE_D; GlobalMembersDsp.LOOP_SIZE_SEC = LOOP_SIZE_SEC_D; GlobalMembersDsp.BMSQ_LUT_SIZE = BMSQ_LUT_SIZE_D; #if QUIET GlobalMembersUtil.quiet = true; #else GlobalMembersUtil.quiet = false; #endif Console.Write("The Analysis & Resynthesis Sound Spectrograph {0}\n", version); RandomNumbers.Seed((int)DateTime.Now.Millisecond); bool doHelp = false; for (i = 0; i < argc; i++) { if (string.Compare(args[i], "/?") == 0) // DOS friendly help { doHelp = true; } if (args[i][0] != '-') // if the argument is not a function { if (in_name == null) // if the input file name hasn't been filled in yet { in_name = args[i]; } else if (out_name == null) // if the input name has been filled but not the output name yet { out_name = args[i]; } else // if both names have already been filled in { Console.Error.WriteLine("You can only have two file names as parameters.\nRemove parameter \"%s\".\nExiting with error.\n", args[i]); Environment.Exit(1); } } else // if the argument is a parameter { if (string.Compare(args[i], "--analysis") == 0 || string.Compare(args[i], "-a") == 0) { mode = 1; } if (string.Compare(args[i], "--sine") == 0 || string.Compare(args[i], "-s") == 0) { mode = 2; } if (string.Compare(args[i], "--noise") == 0 || string.Compare(args[i], "-n") == 0) { mode = 3; } if (string.Compare(args[i], "--quiet") == 0 || string.Compare(args[i], "-q") == 0) { GlobalMembersUtil.quiet = true; } if (string.Compare(args[i], "--linear") == 0 || string.Compare(args[i], "-l") == 0) { GlobalMembersDsp.LOGBASE = 1.0; } if (string.Compare(args[i], "--sample-rate") == 0 || string.Compare(args[i], "-r") == 0) { if (StringUtils.IsNumeric(args[++i])) { samplerate = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--min-freq") == 0 || string.Compare(args[i], "-min") == 0) { if (StringUtils.IsNumeric(args[++i])) { basefreq = Convert.ToDouble(args[i]); if (basefreq == 0) { basefreq = Double.MinValue; // Set it to this extremely close-to-zero number so that it's considered set } } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--max-freq") == 0 || string.Compare(args[i], "-max") == 0) { if (StringUtils.IsNumeric(args[++i])) { maxfreq = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--bpo") == 0 || string.Compare(args[i], "-b") == 0) { if (StringUtils.IsNumeric(args[++i])) { bpo = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--pps") == 0 || string.Compare(args[i], "-p") == 0) { if (StringUtils.IsNumeric(args[++i])) { pixpersec = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--height") == 0 || string.Compare(args[i], "-y") == 0) { if (StringUtils.IsNumeric(args[++i])) { Ysize = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--width") == 0 || string.Compare(args[i], "-x") == 0) { if (StringUtils.IsNumeric(args[++i])) { Xsize = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--loop-size") == 0) { if (StringUtils.IsNumeric(args[++i])) { GlobalMembersDsp.LOOP_SIZE_SEC = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--log-base") == 0) { if (StringUtils.IsNumeric(args[++i])) { GlobalMembersDsp.LOGBASE = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--bmsq-lut-size") == 0) { if (StringUtils.IsNumeric(args[++i])) { GlobalMembersDsp.BMSQ_LUT_SIZE = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--pi") == 0) // lol { if (StringUtils.IsNumeric(args[++i])) { GlobalMembersDsp.PI = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--format-param") == 0 || string.Compare(args[i], "-f") == 0) { if (StringUtils.IsNumeric(args[++i])) { format_param = Convert.ToInt32(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } if (string.Compare(args[i], "--brightness") == 0 || string.Compare(args[i], "-g") == 0) { if (StringUtils.IsNumeric(args[++i])) { brightness = Convert.ToDouble(args[i]); } else { Console.Error.WriteLine(MSG_NUMBER_EXPECTED, args[i - 1]); Environment.Exit(1); } } // TODO implement --duration, -d if (string.Compare(args[i], "--version") == 0 || string.Compare(args[i], "-v") == 0) { Console.Write("Copyright (C) 2005-2008 Michel Rouzic\nProgram last modified by its author on {0}\n", date); Environment.Exit(0); } if (doHelp || string.Compare(args[i], "--help") == 0 || string.Compare(args[i], "-h") == 0) { GlobalMembersArss.PrintHelp(); Environment.Exit(0); } if (string.Compare(args[i], "--adv-help") == 0) { GlobalMembersArss.PrintAdvancedHelp(); Environment.Exit(0); } } } if (in_name != null) // if in_name has already been filled in { fin = new BinaryFile(in_name); // try to open it if (fin == null) { Console.Error.WriteLine("The input file {0} could not be found\nExiting with error.\n", in_name); Environment.Exit(1); } Console.Write("Input file : {0}\n", in_name); } else { if (GlobalMembersUtil.quiet) { Console.Error.WriteLine("Please specify an input file.\nExiting with error.\n"); Environment.Exit(1); } Console.Write("Type 'help' to read the manual page\n"); do { fin = null; Console.Write("Input file : "); in_name = GlobalMembersUtil.GetString(); if (string.Compare(in_name, "help") == 0) // if 'help' has been typed { fin = null; GlobalMembersArss.PrintHelp(); // print the help } else { if (File.Exists(in_name)) { fin = new BinaryFile(in_name); } } }while (fin == null); } if (out_name != null) // if out_name has already been filled in { fout = new BinaryFile(out_name, BinaryFile.ByteOrder.LittleEndian, true); if (fout == null) { Console.Error.WriteLine("The output file {0} could not be opened.\nPlease make sure it isn't opened by any other program and press Return.\nExiting with error.\n", out_name); Environment.Exit(1); } Console.Write("Output file : {0}\n", out_name); } else { if (GlobalMembersUtil.quiet) { Console.Error.WriteLine("Please specify an output file.\nExiting with error.\n"); Environment.Exit(1); } Console.Write("Output file : "); out_name = GlobalMembersUtil.GetString(); fout = null; if (out_name != null && out_name != "") { fout = new BinaryFile(out_name, BinaryFile.ByteOrder.LittleEndian, true); } while (fout == null) { Console.Write("Output file : "); out_name = GlobalMembersUtil.GetString(); if (out_name != null && out_name != "") { fout = new BinaryFile(out_name, BinaryFile.ByteOrder.LittleEndian, true); } } // we will never get here cause BinaryFile does not return a null while (fout == null) { Console.Error.WriteLine("The output file {0} could not be opened.\nPlease make sure it isn't opened by any other program and press Return.\n", out_name); Console.Read(); fout = new BinaryFile(out_name, BinaryFile.ByteOrder.LittleEndian, true); } } // make the string lowercase in_name = in_name.ToLower(); if (mode == 0 && in_name.EndsWith(".wav")) { mode = 1; // Automatic switch to the Analysis mode } if (mode == 0) { do { if (GlobalMembersUtil.quiet) { Console.Error.WriteLine("Please specify an operation mode.\nUse either --analysis (-a), --sine (-s) or --noise (-n).\nExiting with error.\n"); Environment.Exit(1); } Console.Write("Choose the mode (Press 1, 2 or 3) :\n\t1. Analysis\n\t2. Sine synthesis\n\t3. Noise synthesis\n> "); mode = (byte)GlobalMembersUtil.GetFloat(); }while (mode != 1 && mode != 2 && mode != 3); } if (mode == 1) { //sound = GlobalMembersSound_io.wav_in(fin, ref channels, ref samplecount, ref samplerate); // Sound input fin.Close(); sound = GlobalMembersSoundIO.ReadWaveFile(in_name, ref channels, ref samplecount, ref samplerate); // Sound input #if DEBUG Console.Write("samplecount : {0:D}\nchannels : {1:D}\n", samplecount, channels); #endif GlobalMembersArss.SettingsInput(ref Ysize, ref samplecount, ref samplerate, ref basefreq, ref maxfreq, ref pixpersec, ref bpo, ref Xsize, 0); // User settings input image = GlobalMembersDsp.Analyze(ref sound[0], ref samplecount, ref samplerate, ref Xsize, ref Ysize, ref bpo, ref pixpersec, ref basefreq); // Analysis if (brightness != 1.0) { GlobalMembersDsp.BrightnessControl(ref image, ref Ysize, ref Xsize, 1.0 / brightness); } GlobalMembersImageIO.BMPWrite(fout, image, Ysize, Xsize); // Image output } if (mode == 2 || mode == 3) { sound = new double[1][]; image = GlobalMembersImageIO.BMPRead(fin, ref Ysize, ref Xsize); // Image input // if the output format parameter is undefined if (format_param == 0) { if (!GlobalMembersUtil.quiet) // if prompting is allowed { format_param = GlobalMembersSoundIO.GetWaveOutParameters(); } else { format_param = 32; // default is 32 } } GlobalMembersArss.SettingsInput(ref Ysize, ref samplecount, ref samplerate, ref basefreq, ref maxfreq, ref pixpersec, ref bpo, ref Xsize, 1); // User settings input if (brightness != 1.0) { GlobalMembersDsp.BrightnessControl(ref image, ref Ysize, ref Xsize, brightness); } if (mode == 2) { sound[0] = GlobalMembersDsp.SynthesizeSine(ref image, ref Xsize, ref Ysize, ref samplecount, ref samplerate, ref basefreq, ref pixpersec, ref bpo); // Sine synthesis } else { sound[0] = GlobalMembersDsp.SynthesizeNoise(ref image, ref Xsize, ref Ysize, ref samplecount, ref samplerate, ref basefreq, ref pixpersec, ref bpo); // Noise synthesis } GlobalMembersSoundIO.WriteWaveFile(fout, sound, 1, samplecount, samplerate, format_param); } clockb = GlobalMembersUtil.GetTime(); TimeSpan duration = TimeSpan.FromTicks((clockb - GlobalMembersDsp.clockA)); Console.Write("Processing time : {0:D2} m {1:D2} s {1:D2} ms\n", duration.Minutes, duration.Seconds, duration.Milliseconds); GlobalMembersUtil.WinReturn(); }
public static double[][] ReadWaveFile(BinaryFile wavfile, ref int channels, ref int samplecount, ref int samplerate) { double[][] sound; int i = 0; int ic = 0; int[] tag = new int[13]; // Size Description Value // tag[0] 4 RIFF Header RIFF (1179011410) // tag[1] 4 RIFF data size // tag[2] 4 form-type (WAVE etc) (1163280727) // tag[3] 4 Chunk ID "fmt " (0x666D7420) = 544501094 // tag[4] 4 Chunk Data Size 16 + extra format bytes // tag[5] 2 Compression code 1 - 65,535 // tag[6] 2 Number of channels 1 - 65,535 // tag[7] 4 Sample rate 1 - 0xFFFFFFFF // tag[8] 4 Average bytes per second 1 - 0xFFFFFFFF // tag[9] 2 Block align 1 - 65,535 (4) // tag[10] 2 Significant bits per sample 2 - 65,535 (32) // tag[11] 4 IEEE = 1952670054 (0x74636166) = fact chunk // PCM = 1635017060 (0x61746164) (datachunk = 1635017060) // tag[12] 4 IEEE = 4 , PCM = 5292000 (0x0050BFE0) #if DEBUG Console.Write("ReadWaveFile...\n"); #endif for (i = 0; i < 13; i++) // tag reading { tag[i] = 0; if ((i == 5) || (i == 6) || (i == 9) || (i == 10)) { tag[i] = GlobalMembersUtil.ReadUInt16(wavfile); } else { tag[i] = (int)GlobalMembersUtil.ReadUInt32(wavfile); } } //********File format checking******** if (tag[0] != 1179011410 || tag[2] != 1163280727) { Console.Error.WriteLine("This file is not in WAVE format\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } if (tag[3] != 544501094 || tag[4] != 16 || tag[11] != 1635017060) // { Console.Error.WriteLine("This WAVE file format is not currently supported\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } if (tag[10] == 24) { Console.Error.WriteLine("24 bit PCM WAVE files is not currently supported\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } if (tag[5] != WAVE_FORMAT_PCM) { Console.Error.WriteLine("Non PCM WAVE files is not currently supported\n"); GlobalMembersUtil.WinReturn(); Environment.Exit(1); } //--------File format checking-------- channels = tag[6]; samplecount = tag[12] / (tag[10] / 8) / channels; samplerate = tag[7]; sound = new double[channels][]; for (ic = 0; ic < channels; ic++) { sound[ic] = new double[samplecount]; } //********Data loading******** if (tag[10] == 8) { Read8Bit(wavfile, sound, samplecount, channels); } if (tag[10] == 16) { Read16Bit(wavfile, sound, samplecount, channels); } if (tag[10] == 32) { if (tag[5] == WAVE_FORMAT_PCM) { Read32Bit(wavfile, sound, samplecount, channels); } else if (tag[5] == WAVE_FORMAT_IEEE_FLOAT) { Read32BitFloat(wavfile, sound, samplecount, channels); } } //--------Data loading-------- wavfile.Close(); return(sound); }