Запись Wav в файл - C#
Формулировка задачи:
Пишу на C#. Имеется написанный код для записи звука с микрофона в поток(исходник будет ниже). Мне надо сохранить его в файл формата Wav чтоб воспроизводилось в плеере (но если честно файл wav будет нужен для других целей)
Сам сломал голову!!! Если не сложно помогите)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.IO; using Microsoft.DirectX.DirectSound; using Buffer = Microsoft.DirectX.DirectSound.Buffer; namespace vs3 { class Record { public static WaveFormat _waveFormat; //свойство формат public static WaveFormat waveFormat { get { return _waveFormat; } } private static UInt16 sizeBufer = 22050; private static MemoryStream stream; private static MemoryStream tempStream; //свойство размер public static int Length { get { return (int)stream.Length; } } public static byte[] Data { get { switch (regim) { case 0: break; case 1: RecordStop(); break; case 2: PlayStop(); break; } return stream.ToArray(); } } public static byte regim = 0; private static Capture capture; private static CaptureBufferDescription captureBuffDesc; private static CaptureBuffer recordBuff; private static AutoResetEvent autoResetEventRec; private static BufferPositionNotify[] positionNotifyRec; private static Notify notifyRec; private static Thread threadRec; private static Device device; private static Buffer playBuff; private static BufferDescription secondBuffDesc; private static System.Windows.Forms.Control control = null; private static Thread threadPlay; private static AutoResetEvent autoResetEventPlay; private static BufferPositionNotify[] positionNotifyPlay; private static Notify notifyPlay; public static void Create(System.Windows.Forms.Control _control) { control = _control; SetWaveFormat(); SetTempStream(); SetPlayBuff(); SetRecordBuff(); SetNotifyPlay(); SetNotifyRecord(); } private static void SetTempStream() { ushort i, n = (ushort)(sizeBufer); byte[] temp = new byte[n]; if (_waveFormat.BitsPerSample == 8) { for (i = 0; i < n; i++) temp[i] = 127; tempStream = new MemoryStream(temp); return; } if (_waveFormat.BitsPerSample == 16) { for (i = 0; i < n; i++) temp[i] = 0; tempStream = new MemoryStream(temp); return; } } private static void SetWaveFormat() { _waveFormat = new WaveFormat(); _waveFormat.BitsPerSample = 8; _waveFormat.BlockAlign = 1; _waveFormat.Channels = 1; _waveFormat.AverageBytesPerSecond = 22050; _waveFormat.SamplesPerSecond = 22050; _waveFormat.FormatTag = WaveFormatTag.Pcm; } private static void SetRecordBuff() { capture = new Capture(); captureBuffDesc = new CaptureBufferDescription(); captureBuffDesc.BufferBytes = sizeBufer; captureBuffDesc.Format = _waveFormat; recordBuff = new CaptureBuffer(captureBuffDesc, capture); } private static void SetNotifyRecord() { autoResetEventRec = new AutoResetEvent(false); positionNotifyRec = new BufferPositionNotify[2]; positionNotifyRec[0].Offset = sizeBufer / 2 - 1; positionNotifyRec[0].EventNotifyHandle = autoResetEventRec.SafeWaitHandle.DangerousGetHandle(); positionNotifyRec[1].Offset = sizeBufer - 1; positionNotifyRec[1].EventNotifyHandle = autoResetEventRec.SafeWaitHandle.DangerousGetHandle(); notifyRec = new Notify(recordBuff); notifyRec.SetNotificationPositions(positionNotifyRec, 2); } private static void Recording() { int offset = 0; int a, b; recordBuff.GetCurrentPosition(out a, out b); if (a == 0) { offset = sizeBufer / 2; b = sizeBufer / 2; } else if (a < sizeBufer / 2) { offset = sizeBufer / 2; b = sizeBufer / 2 - a; } else { offset = 0; b = sizeBufer - a; } recordBuff.Start(true); autoResetEventRec.WaitOne(Timeout.Infinite, true); recordBuff.Read(a, stream, b, LockFlag.None); for (; ; ) { autoResetEventRec.WaitOne(Timeout.Infinite, true); recordBuff.Read(offset, stream, sizeBufer / 2, LockFlag.None); offset = (offset + sizeBufer / 2) % (sizeBufer); } } private static void RecordStart() { switch (regim) { case 0: break; case 1: RecordStop(); break; case 2: PlayStop(); break; } regim = 1; stream = new MemoryStream(); threadRec = new Thread(new ThreadStart(Recording)); threadRec.Start(); } private static void RecordStop() { if (regim != 1) return; int a, b; threadRec.Abort(); recordBuff.Stop(); recordBuff.GetCurrentPosition(out a, out b); if (a == sizeBufer / 2 || a == sizeBufer) { regim = 0; return; } if (a < sizeBufer / 2) { recordBuff.Read(0, stream, a, LockFlag.None); } else { recordBuff.Read(sizeBufer / 2, stream, a - sizeBufer / 2, LockFlag.None); } regim = 0; } private static void SetPlayBuff() { device = new Device(); device.SetCooperativeLevel(control, CooperativeLevel.Priority); secondBuffDesc = new BufferDescription(); secondBuffDesc.Format = _waveFormat; secondBuffDesc.BufferBytes = sizeBufer; secondBuffDesc.LocateInSoftware = true; secondBuffDesc.ControlPositionNotify = true; secondBuffDesc.ControlFrequency = true; secondBuffDesc.ControlPan = true; secondBuffDesc.ControlVolume = true; playBuff = new Buffer(secondBuffDesc, device); } private static void SetNotifyPlay() { autoResetEventPlay = new AutoResetEvent(false); positionNotifyPlay = new BufferPositionNotify[2]; positionNotifyPlay[0].Offset = sizeBufer / 2 - 1; positionNotifyPlay[0].EventNotifyHandle = autoResetEventPlay.SafeWaitHandle.DangerousGetHandle(); positionNotifyPlay[1].Offset = sizeBufer - 1; positionNotifyPlay[1].EventNotifyHandle = autoResetEventPlay.SafeWaitHandle.DangerousGetHandle(); notifyPlay = new Notify(playBuff); notifyPlay.SetNotificationPositions(positionNotifyPlay, 2); } private static void Playing() { uint i, num = (uint)(stream.Length / (sizeBufer / 2)); int offset, ostatok = (int)stream.Length % (sizeBufer / 2); if (num < 2) { playBuff.Write(0, stream, (int)stream.Length, LockFlag.None); playBuff.Write((int)stream.Length, tempStream, sizeBufer - (int)stream.Length, LockFlag.None); playBuff.Play(0, BufferPlayFlags.Default); return; } playBuff.Write(0, stream, sizeBufer, LockFlag.None); playBuff.Play(0, BufferPlayFlags.Looping); autoResetEventPlay.WaitOne(Timeout.Infinite, true); for (offset = 0, i = 2; i <= num; i++) { if (i != num) { playBuff.Write(offset, stream, sizeBufer / 2, LockFlag.None); } else { playBuff.Write(offset, stream, ostatok, LockFlag.None); playBuff.Write(offset + ostatok, tempStream, sizeBufer / 2 - ostatok, LockFlag.None); } offset = (offset + sizeBufer / 2) % sizeBufer; autoResetEventPlay.WaitOne(Timeout.Infinite, true); } autoResetEventPlay.WaitOne(Timeout.Infinite, true); playBuff.Stop(); regim = 0; } private static void PlayStart() { switch (regim) { case 0: break; case 1: RecordStop(); break; case 2: PlayStop(); break; } regim = 2; stream.Position = 0; playBuff.SetCurrentPosition(0); tempStream.Position = 0; threadPlay = new Thread(new ThreadStart(Playing)); threadPlay.Start(); } private static void PlayStop() { if (regim == 2) { threadPlay.Abort(); playBuff.Stop(); regim = 0; } } public static void Record1() { RecordStart(); } public static void Play() { PlayStart(); } public static int Stop() { switch (regim) { case 1: RecordStop(); return 1; case 2: PlayStop(); return 2; default: return 0; } } public static int Save(string Name) { //Вот надо сюда вставить.написать что-то чтобы сохранить return 0; } } }
Решение задачи: «Запись Wav в файл»
textual
Листинг программы
using System; using System.IO; using System.Runtime.InteropServices; namespace WavFormatCSharp { [StructLayout(LayoutKind.Sequential)] // Структура, описывающая заголовок WAV файла. internal class WavHeader { // WAV-формат начинается с RIFF-заголовка: // Содержит символы "RIFF" в ASCII кодировке // (0x52494646 в big-endian представлении) public UInt32 ChunkId; // 36 + subchunk2Size, или более точно: // 4 + (8 + subchunk1Size) + (8 + subchunk2Size) // Это оставшийся размер цепочки, начиная с этой позиции. // Иначе говоря, это размер файла - 8, то есть, // исключены поля chunkId и chunkSize. public UInt32 ChunkSize; // Содержит символы "WAVE" // (0x57415645 в big-endian представлении) public UInt32 Format; // Формат "WAVE" состоит из двух подцепочек: "fmt " и "data": // Подцепочка "fmt " описывает формат звуковых данных: // Содержит символы "fmt " // (0x666d7420 в big-endian представлении) public UInt32 Subchunk1Id; // 16 для формата PCM. // Это оставшийся размер подцепочки, начиная с этой позиции. public UInt32 Subchunk1Size; // Аудио формат, полный список можно получить здесь [url]http://audiocoding.ru/wav_formats.txt[/url] // Для PCM = 1 (то есть, Линейное квантование). // Значения, отличающиеся от 1, обозначают некоторый формат сжатия. public UInt16 AudioFormat; // Количество каналов. Моно = 1, Стерео = 2 и т.д. public UInt16 NumChannels; // Частота дискретизации. 8000 Гц, 44100 Гц и т.д. public UInt32 SampleRate; // sampleRate * numChannels * bitsPerSample/8 public UInt32 ByteRate; // numChannels * bitsPerSample/8 // Количество байт для одного сэмпла, включая все каналы. public UInt16 BlockAlign; // Так называемая "глубиная" или точность звучания. 8 бит, 16 бит и т.д. public UInt16 BitsPerSample; // Подцепочка "data" содержит аудио-данные и их размер. // Содержит символы "data" // (0x64617461 в big-endian представлении) public UInt32 Subchunk2Id; // numSamples * numChannels * bitsPerSample/8 // Количество байт в области данных. public UInt32 Subchunk2Size; // Далее следуют непосредственно Wav данные. } class Program { static void Main(string[] args) { var header = new WavHeader(); // Размер заголовка var headerSize = Marshal.SizeOf(header); var fileStream = new FileStream("Slipknot - Three Nil.wav", FileMode.Open, FileAccess.Read); var buffer = new byte[headerSize]; fileStream.Read(buffer, 0, headerSize); // Чтобы не считывать каждое значение заголовка по отдельности, // воспользуемся выделением unmanaged блока памяти var headerPtr = Marshal.AllocHGlobal(headerSize); // Копируем считанные байты из файла в выделенный блок памяти Marshal.Copy(buffer, 0, headerPtr, headerSize); // Преобразовываем указатель на блок памяти к нашей структуре Marshal.PtrToStructure(headerPtr, header); // Выводим полученные данные Console.WriteLine("Sample rate: {0}", header.SampleRate); Console.WriteLine("Channels: {0}", header.NumChannels); Console.WriteLine("Bits per sample: {0}", header.BitsPerSample); // Посчитаем длительность воспроизведения в секундах var durationSeconds = 1.0 * header.Subchunk2Size / (header.BitsPerSample / 8.0) / header.NumChannels / header.SampleRate; var durationMinutes = (int)Math.Floor(durationSeconds / 60); durationSeconds = durationSeconds - (durationMinutes * 60); Console.WriteLine("Duration: {0:00}:{1:00}", durationMinutes, durationSeconds); Console.ReadKey(); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д