Search code examples
c#audionaudio

Wav to bitmap conversion in C#


I am trying to write a program to read a .wav file, convert it to a bitmap and then convert the bitmap back to a wav file. I did this already in python with the Wave module and was able to create some sonically interesting degradation this way.

My code runs but I'm not getting the expected result, just white noise.

Wav to bitmap

 private void button1_Click(object sender, EventArgs e)
    {
        System.IO.Stream load_wav = new System.IO.MemoryStream();
        openFileDialog1.Filter = "WAV|*.wav";
        openFileDialog1.ShowDialog();
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            try
            {
                if ((load_wav = openFileDialog1.OpenFile()) != null)
                {
                    using (load_wav)
                    {
                        using (WaveFileReader reader = new WaveFileReader(load_wav))
                        {

                            int BitsPerSample;
                            int SampleRate;
                            BitsPerSample = reader.WaveFormat.BitsPerSample;
                            SampleRate = reader.WaveFormat.SampleRate;
                            string config = SampleRate.ToString();
                            // Write sample config to .ini
                            System.IO.StreamWriter file = new System.IO.StreamWriter(".\\config.ini");
                            file.WriteLine(config);
                            file.Close();
                            if (BitsPerSample == 16) // Check 16bit
                            {
                                // Read WAV
                                byte[] in_buffer = new byte[reader.Length];
                                int read = reader.Read(in_buffer, 0, in_buffer.Length);
                                MessageBox.Show("Load OK");

                                // Convert byte array to stream 
                                Bitmap output = new Bitmap(600, 600); 
                                Rectangle rect = new Rectangle(0, 0, output.Width, output.Height);
                                BitmapData bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);
                                IntPtr ptr = bmpData.Scan0;
                                System.Runtime.InteropServices.Marshal.Copy(in_buffer, 0, ptr, in_buffer.Length);
                                output.UnlockBits(bmpData);
                                pictureBox1.Image = output;
                                output.Save(".\\output.bmp");



                            }

                            else
                            {
                                MessageBox.Show("16 bit WAV files only :-(");
                            }

Bitmap to Wav

 private void button2_Click(object sender, EventArgs e)
    {

        if ((pictureBox1.Image == null))
        {

        }
        else
        {
            // Read sample .ini
            System.IO.StreamReader file = new System.IO.StreamReader(".\\config.ini");
            string config = file.ReadLine();
            file.Close();
            int SampleRate = Convert.ToInt32(config);
            // Convert bmp to byte array
            Bitmap output = Image.FromFile(".\\output.bmp") as Bitmap;
            ImageConverter converter = new ImageConverter();
            byte[] out_bytes = (byte[])converter.ConvertTo(output, typeof(byte[]));
            // Convert byte array to stream
            System.IO.MemoryStream out_stream = new System.IO.MemoryStream(out_bytes);
            // Append valid WAV header to stream
            WaveFormat waveformat = new WaveFormat(SampleRate, 16, 2);
            var reader = new RawSourceWaveStream(out_stream, waveformat);
            using (var convertedStream = WaveFormatConversionStream.CreatePcmStream(reader))
            {
            // Save dialog
                SaveFileDialog savefiledialog1 = new SaveFileDialog();
                savefiledialog1.Title = "export wav";
                savefiledialog1.Filter = "wav|*.wav";
                savefiledialog1.ShowDialog();
                if (savefiledialog1.FileName != "")
                    {
                        WaveFileWriter.CreateWaveFile(savefiledialog1.FileName, convertedStream);
                    }
            }
            out_stream.Close();


        }
    }

I think the problem is with the way I am converting the byte array to stream.


Solution

  • Looked at the bmp output of my python code, the bitmaps produced were 24 bit. The bitmaps produced by my C# code are 32 bit.

    Solved by using EncoderParameters

    // Setup 24 bit bmp encoder
    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.ColorDepth; 
    myEncoder = System.Drawing.Imaging.Encoder.ColorDepth;
    EncoderParameters myEncoderParameters = new EncoderParameters(1);
    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 24L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    var codec = GetEncoderInfo("image/bmp");
    

    The audio output is now a degraded version of the audio input as required.