C# - Проигрывание WAV файла по частям (семплам)

2011-03-18
C#

Иногда возникает необходимость проигрывать из WAV файла определенные части, например, в WAV файл можно сохранить набор звуков для вашего приложения и воспроизводить их оттуда при надобности. Про то как это сделать и пойдет речь в этой статье.

Для этой цели очень хорошо подходит следующий класс:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Media;
using System.IO;
using System.Runtime.InteropServices;

namespace MyNamespace
{
    class Audio
    {
        #region SoundMixer
        [DllImport("coredll.dll", SetLastError = true)]
        protected static extern int waveOutSetVolume(IntPtr device, uint volume);
        //values for 'volume' are between value between 0 (off) and 65536 (max)
        //if there is only one audio device, you can set 'device' to null (or IntPtr.Zero)
        public enum Volumes : int
        {
            OFF = 0,
            LOW = 858993459,
            NORMAL = 1717986918,
            MEDIUM = -1717986919,
            HIGH = -858993460,
            VERY_HIGH = -1
        }
        [DllImport("coredll.dll", SetLastError = true)]
        internal static extern int waveOutSetVolume(IntPtr device, int volume);
        [DllImport("coredll.dll", SetLastError = true)]
        internal static extern int waveOutGetVolume(IntPtr device, ref int volume);
        public void VolumeLevelUP()
        {
            int v = (int)0;
            int Value = 0;
            waveOutGetVolume(IntPtr.Zero, ref v);
            switch (v)
            {
                case (int)Volumes.OFF:
                    Value = (int)Volumes.LOW;
                    break;
                case (int)Volumes.LOW:
                    Value = (int)Volumes.NORMAL;
                    break;
                case (int)Volumes.NORMAL:
                    Value = (int)Volumes.MEDIUM;
                    break;
                case (int)Volumes.MEDIUM:
                    Value = (int)Volumes.HIGH;
                    break;
                case (int)Volumes.HIGH:
                    Value = (int)Volumes.VERY_HIGH;
                    break;
                case (int)Volumes.VERY_HIGH:
                    Value = (int)Volumes.OFF;
                    break;
                default: Value = (int)Volumes.VERY_HIGH;
                    break;
            }
            waveOutSetVolume(IntPtr.Zero, Value);
        }
        public void VolumeLevelDown()
        {
            int v = (int)0;
            int Value = 0;
            waveOutGetVolume(IntPtr.Zero, ref v);
            switch (v)
            {
                case (int)Volumes.OFF:
                    Value = (int)Volumes.VERY_HIGH;
                    break;
                case (int)Volumes.LOW:
                    Value = (int)Volumes.OFF;
                    break;
                case (int)Volumes.NORMAL:
                    Value = (int)Volumes.LOW;
                    break;
                case (int)Volumes.MEDIUM:
                    Value = (int)Volumes.NORMAL;
                    break;
                case (int)Volumes.HIGH:
                    Value = (int)Volumes.MEDIUM;
                    break;
                case (int)Volumes.VERY_HIGH:
                    Value = (int)Volumes.HIGH;
                    break;
                default: Value = (int)Volumes.OFF;
                    break;
            }
            waveOutSetVolume(IntPtr.Zero, Value);
        }

        #endregion
        #region declaretion
        private const byte WavHeaderSize = 40; //Размер заголовка Wav файла без размера тела (4 байта еще)
        private const byte WavHeaderBodyLenghSize = 4;// Размер тела WAV файла
        private string WavFileName; // Путь к файлу
        public byte[] SoundBuffHeader;
        private byte[] SoundBuffMain;
        public int BuffSize = 600000; //размер буфера
        public SoundPlayer Player;
        private FileStream FileStreamWav;
        private Stream SoundStream;
        #endregion
        public Audio(string fileName)
        {
            this.WavFileName = fileName;

            //Буфера wav фала
            SoundBuffHeader = new byte[WavHeaderSize + WavHeaderBodyLenghSize];
            FileStreamWav = File.Open(WavFileName, FileMode.Open);
            SoundBuffMain = new byte[FileStreamWav.Length - WavHeaderSize - WavHeaderBodyLenghSize];
            #region BufferRead
            // Считывание заголовка
            FileStreamWav.Position = 0;
            FileStreamWav.Read(SoundBuffHeader, 0, WavHeaderSize); // Заголовок кроме последней длины

            #endregion
            SoundStream = new MemoryStream();
            Player = new SoundPlayer();
            Player.Stream = new MemoryStream();
        }
        //Воспроизводит WAV файлы
        public void PlaySound(int StartPosition, int StopPosition)
        {
            MemoryClear();

            Player = new SoundPlayer();
            Player.Stream = new MemoryStream();
            int PlayingSoundSize = 0; // Размер тела wav файла
            byte[] DataLenArray;

            PlayingSoundSize = StopPosition - StartPosition;
            // Запись в заголовок информации о размере тела файла
            DataLenArray = BitConverter.GetBytes(PlayingSoundSize);
            DataLenArray.CopyTo(SoundBuffHeader, WavHeaderSize);
            DataLenArray = BitConverter.GetBytes(PlayingSoundSize + WavHeaderSize - WavHeaderBodyLenghSize);
            DataLenArray.CopyTo(SoundBuffHeader, WavHeaderBodyLenghSize);

            //Запись заголовка в проигрываемый файл
            Player.Stream.Position = 0;
            Player.Stream.Write(SoundBuffHeader, 0, SoundBuffHeader.Length);
            // Запись самого тела

            byte[] test = new byte[PlayingSoundSize];
            FileStreamWav.Position = StartPosition;
            FileStreamWav.Read(test, 0, PlayingSoundSize); // Весь файл кроме заголовка
            Player.Stream.Write(test, 0, test.Length);
            Player.Stream.Position = 0;

            Player.Load();
            Player.Play();

        }
        //Остановка плеера
        public void StopPlaying()
        {
            Player.Stop();
            MemoryClear();
        }

        private void MemoryClear()
        {
            try
            {
                Player.Stream.Close();
                Player.Dispose();
                GC.SuppressFinalize(Player);
                GC.Collect();
                long check3 = GC.GetTotalMemory(true);
            }
            catch (Exception v)
            {
            }
        }
    }
}

Далее, создаем экземпляр данного класса, указав в качестве параметра WAV файл и воспроизводим необходимые нам отрезки из данного файла.

Взято с http://forum.vingrad.ru/forum/topic-261721/anchor-entry1885131/0.html