internal unsafe void SaveAsWaveFile(string filePath) { const int chunkSize = 4096; FileStream file = null; IntPtr data = IntPtr.Zero; try { // Create the file file = new FileStream(filePath, FileMode.Create, FileAccess.Write); // Alocate memory for the PCM data buffer data = Marshal.AllocHGlobal(chunkSize); // Create a holding buffer that the PCM data will be copied into byte[] buffer = new byte[chunkSize]; uint totalSize = 0; uint bytesRead = 0; // Get the length of the sound in PCM bytes this.LengthUnit = TimeUnits.PcmByte; uint pcmLength = this.FmodLength; // Create the WAV structures FmtChunk fmtChunk = new FmtChunk(); DataChunk dataChunk = new DataChunk(); WavHeader wavHeader = new WavHeader(); RiffChunk riffChunk = new RiffChunk(); fmtChunk.Chunk = new RiffChunk(); fmtChunk.Chunk.Id = new char[4] { 'f', 'm', 't', ' ' }; fmtChunk.Chunk.Size = Marshal.SizeOf(fmtChunk) - Marshal.SizeOf(riffChunk); fmtChunk.FormatTag = 1; fmtChunk.NumberOfChannels = (ushort)this.NumberOfChannels; fmtChunk.SamplesPerSecond = (uint)this.DefaultSettings.Frequency; fmtChunk.AverageBytesPerSecond = (uint)(this.DefaultSettings.Frequency * this.NumberOfChannels * this.NumberOfBitsPerSample / 8); fmtChunk.BlockSize = (ushort)(1 * this.NumberOfChannels * this.NumberOfBitsPerSample / 8); fmtChunk.NumberOfBitsPerSample = (ushort)this.NumberOfBitsPerSample; dataChunk.Chunk = new RiffChunk(); dataChunk.Chunk.Id = new char[4] { 'd', 'a', 't', 'a' }; dataChunk.Chunk.Size = (int)pcmLength; wavHeader.Chunk = new RiffChunk(); wavHeader.Chunk.Id = new char[4] { 'R', 'I', 'F', 'F' }; wavHeader.Chunk.Size = (int)(Marshal.SizeOf(fmtChunk) + Marshal.SizeOf(riffChunk) + pcmLength); wavHeader.RiffType = new char[4] { 'W', 'A', 'V', 'E' }; // Write out the WAV header. IntPtr wavHeaderPtr = Marshal.AllocHGlobal(Marshal.SizeOf(wavHeader)); IntPtr fmtChunkPtr = Marshal.AllocHGlobal(Marshal.SizeOf(fmtChunk)); IntPtr dataChunkPtr = Marshal.AllocHGlobal(Marshal.SizeOf(dataChunk)); byte[] wavHeaderBytes = new byte[Marshal.SizeOf(wavHeader)]; byte[] fmtChunkBytes = new byte[Marshal.SizeOf(fmtChunk)]; byte[] dataChunkBytes = new byte[Marshal.SizeOf(dataChunk)]; Marshal.StructureToPtr(wavHeader, wavHeaderPtr, false); Marshal.Copy(wavHeaderPtr, wavHeaderBytes, 0, Marshal.SizeOf(wavHeader)); Marshal.StructureToPtr(fmtChunk, fmtChunkPtr, false); Marshal.Copy(fmtChunkPtr, fmtChunkBytes, 0, Marshal.SizeOf(fmtChunk)); Marshal.StructureToPtr(dataChunk, dataChunkPtr, false); Marshal.Copy(dataChunkPtr, dataChunkBytes, 0, Marshal.SizeOf(dataChunk)); file.Write(wavHeaderBytes, 0, Marshal.SizeOf(wavHeader)); file.Write(fmtChunkBytes, 0, Marshal.SizeOf(fmtChunk)); file.Write(dataChunkBytes, 0, Marshal.SizeOf(dataChunk)); do { // Read PCM data from the sound bytesRead = Read(data, chunkSize); // Copy the PCM data into the buffer Marshal.Copy(data, buffer, 0, chunkSize); // Write the PCM data to the FileStream file.Write(buffer, 0, (int)bytesRead); // Increment totalRead totalSize += bytesRead; } while (currentResult == Result.Ok && bytesRead == chunkSize); //file.Close(); } catch (Exception ex) { throw new ApplicationException("There was an error saving this sound to " + filePath + " : " + currentResult.ToString() + ":" + ex.Message, ex); } finally { // Always free the data pointer if (data != IntPtr.Zero) Marshal.FreeHGlobal(data); // Always close the file if (file != null) file.Close(); } }
internal unsafe void SaveAsWaveFile(string filePath) { const int chunkSize = 4096; FileStream file = null; IntPtr data = IntPtr.Zero; try { // Create the file file = new FileStream(filePath, FileMode.Create, FileAccess.Write); // Alocate memory for the PCM data buffer data = Marshal.AllocHGlobal(chunkSize); // Create a holding buffer that the PCM data will be copied into byte[] buffer = new byte[chunkSize]; uint totalSize = 0; uint bytesRead = 0; // Get the length of the sound in PCM bytes this.LengthUnit = TimeUnits.PcmByte; uint pcmLength = this.FmodLength; // Create the WAV structures FmtChunk fmtChunk = new FmtChunk(); DataChunk dataChunk = new DataChunk(); WavHeader wavHeader = new WavHeader(); RiffChunk riffChunk = new RiffChunk(); fmtChunk.Chunk = new RiffChunk(); fmtChunk.Chunk.Id = new char[4] { 'f', 'm', 't', ' ' }; fmtChunk.Chunk.Size = Marshal.SizeOf(fmtChunk) - Marshal.SizeOf(riffChunk); fmtChunk.FormatTag = 1; fmtChunk.NumberOfChannels = (ushort)this.NumberOfChannels; fmtChunk.SamplesPerSecond = (uint)this.DefaultSettings.Frequency; fmtChunk.AverageBytesPerSecond = (uint)(this.DefaultSettings.Frequency * this.NumberOfChannels * this.NumberOfBitsPerSample / 8); fmtChunk.BlockSize = (ushort)(1 * this.NumberOfChannels * this.NumberOfBitsPerSample / 8); fmtChunk.NumberOfBitsPerSample = (ushort)this.NumberOfBitsPerSample; dataChunk.Chunk = new RiffChunk(); dataChunk.Chunk.Id = new char[4] { 'd', 'a', 't', 'a' }; dataChunk.Chunk.Size = (int)pcmLength; wavHeader.Chunk = new RiffChunk(); wavHeader.Chunk.Id = new char[4] { 'R', 'I', 'F', 'F' }; wavHeader.Chunk.Size = (int)(Marshal.SizeOf(fmtChunk) + Marshal.SizeOf(riffChunk) + pcmLength); wavHeader.RiffType = new char[4] { 'W', 'A', 'V', 'E' }; // Write out the WAV header. IntPtr wavHeaderPtr = Marshal.AllocHGlobal(Marshal.SizeOf(wavHeader)); IntPtr fmtChunkPtr = Marshal.AllocHGlobal(Marshal.SizeOf(fmtChunk)); IntPtr dataChunkPtr = Marshal.AllocHGlobal(Marshal.SizeOf(dataChunk)); byte[] wavHeaderBytes = new byte[Marshal.SizeOf(wavHeader)]; byte[] fmtChunkBytes = new byte[Marshal.SizeOf(fmtChunk)]; byte[] dataChunkBytes = new byte[Marshal.SizeOf(dataChunk)]; Marshal.StructureToPtr(wavHeader, wavHeaderPtr, false); Marshal.Copy(wavHeaderPtr, wavHeaderBytes, 0, Marshal.SizeOf(wavHeader)); Marshal.StructureToPtr(fmtChunk, fmtChunkPtr, false); Marshal.Copy(fmtChunkPtr, fmtChunkBytes, 0, Marshal.SizeOf(fmtChunk)); Marshal.StructureToPtr(dataChunk, dataChunkPtr, false); Marshal.Copy(dataChunkPtr, dataChunkBytes, 0, Marshal.SizeOf(dataChunk)); file.Write(wavHeaderBytes, 0, Marshal.SizeOf(wavHeader)); file.Write(fmtChunkBytes, 0, Marshal.SizeOf(fmtChunk)); file.Write(dataChunkBytes, 0, Marshal.SizeOf(dataChunk)); do { // Read PCM data from the sound bytesRead = Read(data, chunkSize); // Copy the PCM data into the buffer Marshal.Copy(data, buffer, 0, chunkSize); // Write the PCM data to the FileStream file.Write(buffer, 0, (int)bytesRead); // Increment totalRead totalSize += bytesRead; }while (currentResult == Result.Ok && bytesRead == chunkSize); //file.Close(); } catch (Exception ex) { throw new ApplicationException("There was an error saving this sound to " + filePath + " : " + currentResult.ToString() + ":" + ex.Message, ex); } finally { // Always free the data pointer if (data != IntPtr.Zero) { Marshal.FreeHGlobal(data); } // Always close the file if (file != null) { file.Close(); } } }