Donnerstag, 10. März 2011

Wave Dateien schreiben

Im vorigen Post wurde gezeigt, wie man Wave Dateien byteweise einlesen kann. Jetzt möchte ich zeigen, wie man die Audiodateien erstellt.
Hierbei beschränke ich mich nur auf die Umkehrung des vorher beschriebenen Lesens, ich zeige in diesem Post also wie man eine vorher eingelesene Wave Datei wieder als Datei auf die Festplatte schreibt.
Im vorigen Post wurde der Aufbau von Wave Dateien und allerlei anderes Grundlegendes erläutert, deshalb poste ich hier nur kurz den Quellcode von 2 Funktionen, um die die Klasse WaveFile erweitert werden muss, damit Wave Dateien auch geschrieben werden können.
Das Prinzip ist analog zur Implementierung des Lesens, nacheinander werden die 3 Blöcke "RIFF", "fmt " und "data" in eine Datei geschrieben.

        public void StoreWave(string path)
        {
            System.IO.FileStream fs = System.IO.File.OpenWrite(path); // zu schreiben Wave Datei öffnen / erstellen
            StoreChunk(fs, "RIFF"); // RIFF Chunk schreiben
            StoreChunk(fs, "fmt "); // fmt Chunk schreiben
            StoreChunk(fs, "data"); // data Chunk schreiben
        }

        private void StoreChunk(System.IO.FileStream fs, string chunkID)
        {
            System.Text.ASCIIEncoding Decoder = new ASCIIEncoding();
            // den Namen in Bytes konvertieren und schreiben
            fs.Write(Decoder.GetBytes(chunkID), 0, 4);

            if (chunkID == "RIFF")
            {
                // im RIFF Chunk, FileSize als Größe und das Audioformat schreiben
                fs.Write(System.BitConverter.GetBytes(FileSize), 0, 4);
                fs.Write(Decoder.GetBytes(Format), 0, 4);
            }
            if (chunkID == "fmt ")
            {
                // beim fmt Chunk die Größe dieses sowie die weiteren kodierten Informationen schreiben
                fs.Write(System.BitConverter.GetBytes(FmtChunkSize), 0, 4);
                fs.Write(System.BitConverter.GetBytes(AudioFormat), 0, 2);
                fs.Write(System.BitConverter.GetBytes(NumChannels), 0, 2);
                fs.Write(System.BitConverter.GetBytes(SampleRate), 0, 4);
                fs.Write(System.BitConverter.GetBytes(ByteRate), 0, 4);
                fs.Write(System.BitConverter.GetBytes(BlockAlign), 0, 2);
                fs.Write(System.BitConverter.GetBytes(BitsPerSample), 0, 2);
            }
            if (chunkID == "data")
            {
                // beim data Chunk die Größe des Datenblocks als Größenangabe schreiben
                fs.Write(System.BitConverter.GetBytes(DataSize), 0, 4);
                // dann die einzelnen Amplituden, wie beschrieben Sample für Sample mit jeweils allen
                // Audiospuren, schreiben
                for (int i = 0; i < Data[0].Length; i++)
                {
                    for (int j = 0; j < NumChannels; j++)
                    {
                        fs.Write(System.BitConverter.GetBytes(Data[j][i]), 0, BlockAlign / NumChannels);
                    }
                }
            }
        }

Eine beispielhafte Implementierung, welche eine Wave Datei einliest und diese schließlich wieder als Datei auf die Festplatte schreibt, könnte so aussehen:

WaveFile WF1 = new WaveFile();
WF1.LoadWave(@"C:\Users\User\Desktop\mix.wav");
WF1.StoreWave(@"C:\Users\User\Desktop\stored.wav");

Keine Kommentare:

Kommentar veröffentlichen