コード例 #1
0
ファイル: Sound.cs プロジェクト: bossaia/alexandrialibrary
		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();
			}
		}