Ejemplo n.º 1
0
 public static Info AnalyzeFile(string bpcmFile)
 {
     using (FileStream s = new FileStream(bpcmFile, FileMode.Open, FileAccess.Read, FileShare.Read, 1048576, FileOptions.RandomAccess))
     {
         BitstreamReader BPCM        = new BitstreamReader(s);
         double          duration    = (double)BPCM.Analysis.DurationSampleCount / BPCM.Analysis.FrameSet[0].SamplingRate;
         TimeSpan        dur         = TimeSpan.FromSeconds(duration);
         string          strDuration = String.Format("{0:00}d {1:00}h {2:00}m {3:00}s {4:000.000}ms", dur.Days, dur.Hours, dur.Minutes, dur.Seconds, (duration - Math.Floor(duration)) * 1000);
         return(new Info()
         {
             NumberOfChannels = BPCM.Analysis.FrameSet[0].Channels
             , SamplingRate = BPCM.Analysis.FrameSet[0].SamplingRate
             , Duration = BPCM.Analysis.Duration
             , DurationSampleCount = BPCM.Analysis.DurationSampleCount
             , DurationString = strDuration
             , BitrateMin = BPCM.Analysis.BitrateMinimum
             , BitrateAvg = BPCM.Analysis.BitrateAverage
             , BitrateMax = BPCM.Analysis.BitrateMaximum
             , BlockSizeNominal = BPCM.Analysis.BlockSizeNominal
             , BlockSizeAverage = BPCM.Analysis.BlockSizeAverage
             , BlockSizeMaximum = BPCM.Analysis.BlockSizeMaximum
             , BlockSizeMinimum = BPCM.Analysis.BlockSizeMinimum
             , FrameSampleCountHistogram = BPCM.Analysis.FrameSampleCountHistogram
             , FrameSet = BPCM.Analysis.FrameSet
             , CompressionUsed = BPCM.Analysis.CompressionUsed
             , CompressionUsedString = string.Join(", ", BPCM.Analysis.CompressionUsed.ToArray())
         });
     }
 }
Ejemplo n.º 2
0
        public BPCMWaveProvider(BitstreamReader stream, double srf = 1)
        {
            streamBPCM   = stream;
            frame0       = streamBPCM.Analysis.FrameSet[0];
            currentFrame = frame0;
            vol          = 1;
            srfactor     = srf;
            int speedSR = (int)Math.Round(frame0.SamplingRate * srf, 0);

            waveFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm, speedSR, frame0.Channels, speedSR * frame0.Channels * 2, frame0.Channels * 2, 16);
            rb         = new RingBuffer(2097152);
            tsOffset   = 0;
        }
Ejemplo n.º 3
0
        public Player(string bpcmFile, ConfigurationBean config)
        {
            //First of all check the configs and if in doubt, use default values
            if (config.WaveOutDevice > WaveOut.DeviceCount || config.WaveOutDevice < 0)
            {
                config.WaveOutDevice = 0;
            }
            if (config.WaveOutBufferCount < 2)
            {
                config.WaveOutBufferCount = 2;
            }
            if (config.WaveOutBufferSize == 0)
            {
                config.WaveOutBufferSize = 100;
            }
            if (config.Volume > 1)
            {
                config.Volume = 1f;
            }
            if (config.Volume < 0)
            {
                config.Volume = 0f;
            }
            if (config.PlaybackRate == 0)
            {
                config.PlaybackRate = 1;
            }
            _config = config;

            //Open the BPCM file
            _BPCMFile   = new FileStream(bpcmFile, FileMode.Open, FileAccess.Read, FileShare.Read, 1048576, FileOptions.RandomAccess);
            _BPCMStream = new BitstreamReader(_BPCMFile);
            _BPCMStream.EnableDither = _config.EnableDithering;

            __INTERNAL_WaveOutInit();

            //Determine the used device and fire the init event once.
            WaveOutCapabilities devcaps = WaveOut.GetCapabilities(0);

            for (int x = 0; x < WaveOut.DeviceCount; x++)
            {
                if (x == _WaveOut.DeviceNumber || x != 0)
                {
                    devcaps = WaveOut.GetCapabilities(x);
                }
            }
            _config.WaveOutInitializedEvent?.Invoke(devcaps);
        }
Ejemplo n.º 4
0
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    _WaveOut.Stop();
                    _WaveOut.Dispose();
                    _WaveOut = null;
                    _BPCMFile.Dispose();
                    _BPCMFile = null;
                }

                _BPCMStream       = null;
                _BPCMWaveProvider = null;

                disposedValue = true;
            }
        }
Ejemplo n.º 5
0
        public static void DecodeBPCMFile(string bpcmFile, string waveFile, dgUpdate statusCallback = null, double updateInterval = 250, bool Analyze = true, dgBPCMFileOpened fileOpenedEvent = null, bool enableDither = true)
        {
            using (FileStream s = new FileStream(bpcmFile, FileMode.Open, FileAccess.Read, FileShare.Read, 1048576, FileOptions.RandomAccess))
            {
                BitstreamReader BPCM        = new BitstreamReader(s);
                double          duration    = (double)BPCM.Analysis.DurationSampleCount / BPCM.Analysis.FrameSet[0].SamplingRate;
                TimeSpan        dur         = TimeSpan.FromSeconds(duration);
                string          strDuration = String.Format("{0:00}d {1:00}h {2:00}m {3:00}s {4:000.000}ms", dur.Days, dur.Hours, dur.Minutes, dur.Seconds, (duration - Math.Floor(duration)) * 1000);
                fileOpenedEvent?.Invoke(new Info()
                {
                    NumberOfChannels            = BPCM.Analysis.FrameSet[0].Channels
                    , SamplingRate              = BPCM.Analysis.FrameSet[0].SamplingRate
                    , Duration                  = BPCM.Analysis.Duration
                    , DurationSampleCount       = BPCM.Analysis.DurationSampleCount
                    , DurationString            = strDuration
                    , BitrateMin                = BPCM.Analysis.BitrateMinimum
                    , BitrateAvg                = BPCM.Analysis.BitrateAverage
                    , BitrateMax                = BPCM.Analysis.BitrateMaximum
                    , BlockSizeNominal          = BPCM.Analysis.BlockSizeNominal
                    , BlockSizeAverage          = BPCM.Analysis.BlockSizeAverage
                    , BlockSizeMaximum          = BPCM.Analysis.BlockSizeMaximum
                    , BlockSizeMinimum          = BPCM.Analysis.BlockSizeMinimum
                    , FrameSampleCountHistogram = BPCM.Analysis.FrameSampleCountHistogram
                    , FrameSet                  = BPCM.Analysis.FrameSet
                    , CompressionUsed           = BPCM.Analysis.CompressionUsed
                    , CompressionUsedString     = string.Join(", ", BPCM.Analysis.CompressionUsed.ToArray())
                });

                BPCM.EnableDither = enableDither;

                using (FileStream streamOut = new FileStream(waveFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 1048576, FileOptions.RandomAccess))
                {
                    WAVEWriter w = new WAVEWriter(streamOut, new WAVEFormat()
                    {
                        nSamplesPerSec        = (uint)BPCM.Analysis.FrameSet[0].SamplingRate
                        , nChannels           = (ushort)BPCM.Analysis.FrameSet[0].Channels
                        , nBitsPerSample      = 16
                        , nBlockAlign         = (ushort)(BPCM.Analysis.FrameSet[0].Channels * 2)
                        , nAvgBytesPerSeconds = (uint)(BPCM.Analysis.FrameSet[0].Channels * 2 * BPCM.Analysis.FrameSet[0].SamplingRate)
                        , wFormatTag          = 1 //PCM signed integer Intel
                    });

                    Stopwatch ssw = new Stopwatch();
                    ssw.Start();

                    double   precisepos;
                    TimeSpan pos;

                    while (true)
                    {
                        object tmp = BPCM.GetFrame();
                        if (tmp.Equals(false))
                        {
                            break;
                        }
                        Frame frame = (Frame)tmp;
                        tmp = null;

                        if (frame.Data?.Length > 0)
                        {
                            w.Write(frame.Data);
                        }
                        else
                        {
                            w.WriteSilence((double)frame.SampleCount / frame.SamplingRate);
                        }

                        if (ssw.ElapsedMilliseconds >= updateInterval && statusCallback != null)
                        {
                            precisepos = (double)w.PCMPosition / w.fmtHeader.nAvgBytesPerSeconds;
                            pos        = TimeSpan.FromSeconds(precisepos);
                            statusCallback?.Invoke(new Status()
                            {
                                BytesWritten     = w.PCMPosition
                                , Position       = (double)w.PCMPosition / w.fmtHeader.nAvgBytesPerSeconds
                                , PositionString = String.Format("{0:00}d {1:00}h {2:00}m {3:00}s {4:000.000}ms", pos.Days, pos.Hours, pos.Minutes, pos.Seconds, (precisepos - Math.Floor(precisepos)) * 1000)
                                , PercentageDone = (double)s.Position / s.Length * 100
                            });
                            ssw.Restart();
                        }
                        if (BPCM.EOF)
                        {
                            break;
                        }
                    }

                    precisepos = (double)w.PCMPosition / w.fmtHeader.nAvgBytesPerSeconds;
                    pos        = TimeSpan.FromSeconds(precisepos);

                    statusCallback?.Invoke(new Status()
                    {
                        BytesWritten     = w.PCMPosition
                        , Position       = (double)w.PCMPosition / w.fmtHeader.nAvgBytesPerSeconds
                        , PositionString = String.Format("{0:00}d {1:00}h {2:00}m {3:00}s {4:000.000}ms", pos.Days, pos.Hours, pos.Minutes, pos.Seconds, (precisepos - Math.Floor(precisepos)) * 1000)
                        , PercentageDone = 100
                    });
                    w.Finalize();
                }
            }
        }
Ejemplo n.º 6
0
        static void play(string bpcmfile, float volume, double rate, int output_device = 0, bool enDither = true)
        {
            Console.WriteLine("{0,-20} {1}", "File path:", new FileInfo(bpcmfile).Directory.FullName);
            Console.WriteLine("{0,-20} {1}", "File name:", new FileInfo(bpcmfile).Name);

            //Analyse stream
            FileStream s = new FileStream(bpcmfile, FileMode.Open, FileAccess.Read, FileShare.Read, 1048576, false);

            void AnalyisisProgress(float percentDone)
            {
                Console.CursorLeft = 0;
                Console.Write(String.Concat(Enumerable.Repeat(" ", Console.BufferWidth - 1)));
                Console.CursorLeft = 0;
                Console.Write("{0,-20} {1, -4:0.00} percent done.", "Analyzing file:", percentDone);
            }

            BitstreamReader p = new BitstreamReader(s, aupevt: AnalyisisProgress);

            p.EnableDither = enDither;

            Console.CursorLeft = 0;
            Console.Write(String.Concat(Enumerable.Repeat(" ", Console.BufferWidth - 1)));
            Console.CursorLeft = 0;

            //Print info
            Console.WriteLine("{0,-20} {1}", "File size:", Helpers.ByteFormatter.FormatBytes(s.Length));
            printInfo(p.Analysis);
            Console.WriteLine(String.Concat(Enumerable.Repeat("\x2509", 80)));

            //Box line and corner as well as connection chars
            const string strFcF = "\x250C", strFc7 = "\x2510", strFcL = "\x2514", strFcJ = "\x2518"
            , strFbI = "\x2502", strFbL = "\x2500", strFbT = "\x252C", strFbUMT = "\x2534"
            , strFbLT = "\x251C", strFbMMT = "\x253C", strFbRT = "\x2524", strAUD = "\x2195", strALR = "\x2194";

            //VU meter chars
            string[,] arrVU = { { " ", "\x2580" }, { " ", "\x2584" } };
            //string[,] arrVU = { { " ", "\x25AE" }, { " ", "\x25AE" } };

            int nBuffers = 16;
            int fnumLen  = p.Analysis.FrameSet.Count.ToString().Length;

            if (fnumLen < 6)
            {
                fnumLen = 6;
            }
            int    currFrame = 0;
            double currTS    = 0;

            double           speed    = rate;
            bool             dontExit = false;
            WaveOutEvent     wavOut;
            BPCMWaveProvider bpcmWP = new BPCMWaveProvider(p, speed);

            //Prepare lines
            string strTsLine = String.Concat(Enumerable.Repeat(strFbL, 22))
            , strFNumLine    = String.Concat(Enumerable.Repeat(strFbL, fnumLen))
            , strBitRateLine = String.Concat(Enumerable.Repeat(strFbL, 6))
            , strComprLine   = String.Concat(Enumerable.Repeat(strFbL, 10))
            , strVolumeLine  = String.Concat(Enumerable.Repeat(strFbL, 6))
            , strRateLine    = String.Concat(Enumerable.Repeat(strFbL, 5))
            , strVULine      = String.Concat(Enumerable.Repeat(strFbL, 58))
            , strVUScale     = "-\x221e\x2508"
                               + "-60" + string.Concat(Enumerable.Repeat("\x2508", 6))
                               + "-50" + string.Concat(Enumerable.Repeat("\x2508", 6))
                               + "-40" + string.Concat(Enumerable.Repeat("\x2508", 7))
                               + "-30" + string.Concat(Enumerable.Repeat("\x2508", 6))
                               + "-20" + string.Concat(Enumerable.Repeat("\x2508", 4))
                               + "-12" + string.Concat(Enumerable.Repeat("\x2508", 2))
                               + "-6\x2508-3\x25080"
            , strVUBlank = String.Concat(Enumerable.Repeat(" ", 58));


            void readDone(Frame CurrentFrame)
            {
                currFrame = CurrentFrame.FrameNumber;
                ADPCM.ADPCM4BIT.VolumeInfo vi = CurrentFrame.VolumeInfo;

                currTS = CurrentFrame.TimeStamp;
                TimeSpan tsnPos = TimeSpan.FromSeconds(currTS);
                int      days   = tsnPos.Days; if (days > 9)
                {
                    days = 9;                                   //Clamp days never to be more than 9.
                }
                string strPos = String.Format("{0}d {1:00}h {2:00}m {3:00}s {4:000}ms", days, tsnPos.Hours, tsnPos.Minutes, tsnPos.Seconds, tsnPos.Milliseconds);

                //Debug.WriteLine(strPos);

                //Refresh the status line
                Console.CursorLeft = 0;
                Console.Write(strFbI + strALR + "{0,21}" + strFbI + "{1," + fnumLen + "}" + strFbI + "{2,6}" + strFbI + "{3,-10}" + strFbI + strAUD + "{4,4}%" + strFbI + "x{5,4}" + strFbI,
                              strPos, currFrame + 1, Math.Round(((CurrentFrame.DataLength + CurrentFrame.HederLength) / CurrentFrame.Duration) * 8, 0), CurrentFrame.CompressionTypeDescr, Math.Round(wavOut.Volume * 100, 1), speed);

                //Calculate bar length from dB value.
                const int max = 57, lowpoint = 62; //lowpoint is the positive value of the minus dB the scale will start
                int       L = (int)Math.Round(((vi.dbPeakL + lowpoint) / lowpoint) * max);

                if (L < 0)
                {
                    L = 0;        //clamp
                }
                int R = (int)Math.Round(((vi.dbPeakR + lowpoint) / lowpoint) * max);

                if (R < 0)
                {
                    R = 0;        //clamp
                }
                string strVUMeterL = arrVU[0, 1] + String.Concat(Enumerable.Repeat(arrVU[0, 1], L)) + String.Concat(Enumerable.Repeat(arrVU[0, 0], max - L));
                string strVUMeterR = arrVU[1, 1] + String.Concat(Enumerable.Repeat(arrVU[1, 1], R)) + String.Concat(Enumerable.Repeat(arrVU[1, 0], max - R));

                Console.CursorLeft = 0;
                Console.CursorTop += 2;
                Console.WriteLine(strFbI + "L " + strVUMeterL + strFbI);

                Console.CursorLeft = 0;
                Console.CursorTop += 1;
                Console.WriteLine(strFbI + "R " + strVUMeterR + strFbI);

                Console.CursorLeft = 0;
                Console.CursorTop -= 5;
            }

            void woutInit()
            {
                wavOut = new WaveOutEvent();
                wavOut.DeviceNumber     = output_device;
                wavOut.DesiredLatency   = 100 * wavOut.NumberOfBuffers;
                wavOut.PlaybackStopped += stopped;
                wavOut.Init(bpcmWP);
                wavOut.Volume         = volume;
                nBuffers              = wavOut.NumberOfBuffers;
                Console.CursorVisible = false;
            }

            woutInit();

            bpcmWP.readDone = readDone;
            bpcmWP.volume   = 1;

            void changeRate()
            {
                if (WaveOut.GetCapabilities(wavOut.DeviceNumber).SupportsPlaybackRateControl&& 1 == 2)
                {
                    wavOut.Rate = (float)speed;
                }
                else
                {
                    reinitBPCMWaveSrc();
                }
            }

            void reinitBPCMWaveSrc()
            {
                dontExit = true;
                volume   = wavOut.Volume;
                wavOut.Stop();
                wavOut.Dispose();
                wavOut = null;
                bpcmWP = null;
                GC.Collect();
                bpcmWP          = new BPCMWaveProvider(p, speed);
                bpcmWP.volume   = 1;
                bpcmWP.readDone = readDone;
                p.Seek(currFrame - 1); //fix for skipping
                woutInit();
                wavOut.Play();
            }

            string DeviceName = "";

            for (int x = 0; x < WaveOut.DeviceCount; x++)
            {
                if (x == wavOut.DeviceNumber)
                {
                    DeviceName = "[" + x + "] " + WaveOut.GetCapabilities(x).ProductName;
                    break;
                }
            }

            //Playback stopped event handler method
            void stopped(object sender, StoppedEventArgs e)
            {
                if (!dontExit)
                {
                    exitNow();
                }
                else
                {
                    dontExit = false;
                }
            }

            //Drawing status box
            Console.WriteLine("{0,-20} {1}", "Playing on:", DeviceName);
            Console.WriteLine("");

            //Upper corner of box
            Console.WriteLine(strFcF + strTsLine + strFbT + strFNumLine + strFbT + strBitRateLine + strFbT + strComprLine + strFbT + strVolumeLine + strFbT + strRateLine + strFc7);
            //Descriptions
            Console.WriteLine(strFbI + "{0,-22}" + strFbI + "{1,-" + fnumLen + "}" + strFbI + "{2,6}" + strFbI + "{3,-10}" + strFbI + "{4,-6}" + strFbI + "{5,-5}" + strFbI, "timestamp", "frame#", "bit/s", "compr.", "volume", "rate");
            //Divider lines
            Console.WriteLine(strFbLT + strTsLine + strFbMMT + strFNumLine + strFbMMT + strBitRateLine + strFbMMT + strComprLine + strFbMMT + strVolumeLine + strFbMMT + strRateLine + strFbRT);
            //Status line (empty here)
            Console.WriteLine(strFbI + strALR + "{0,21}" + strFbI + "{1," + fnumLen + "}" + strFbI + "{2,6}" + strFbI + "{3,-10}" + strFbI + strAUD + "{4,4}%" + strFbI + "{5,5}" + strFbI, "N/A", "N/A", "N/A", "N/A", "N/A", "N/A");
            //Bottom corner of box
            Console.WriteLine(strFbLT + strTsLine + strFbUMT + strFNumLine + strFbUMT + strBitRateLine + strFbUMT + strComprLine + strFbUMT + strVolumeLine + strFbUMT + strRateLine + strFbRT);

            //VU top
            //Console.WriteLine(strFcF + strFbL + strFbL + strVULine + strFc7);
            Console.WriteLine(strFbI + "L " + strVUBlank + strFbI);
            //VU middle
            Console.WriteLine(strFbI + " " + strVUScale + strFbI);
            Console.WriteLine(strFbI + "R " + strVUBlank + strFbI);
            //VU bottom
            Console.WriteLine(strFcL + strFbL + strFbL + strVULine + strFcJ);

            Console.WriteLine("");
            Console.WriteLine("Volume:  Up/Down 1% steps, Hold CTRL 0.1% steps, PgUp/PgDwn 10% steps");
            Console.WriteLine("Seeking: Left/Right 5 secs, Hold CTRL 1 sec steps, Home for beginning");
            Console.WriteLine("Speed:   S, D and F. You'll figure it out. ;) You can also use CTRL!");

            //Set cursor top position to the status line.
            Console.CursorTop -= 10;



            bool exit = false;

            void exitNow()
            {
                try
                {
                    Console.CursorTop    += 10;
                    Console.CursorLeft    = 0;
                    Console.CursorVisible = true;
                    wavOut?.Dispose();
                    p = null;
                } catch
                {
                }
                Environment.Exit(0);
            }

            //Start playback
            wavOut.Play();

            //Crude key scanning
            while (!exit)
            {
                ConsoleKeyInfo key = Console.ReadKey(true);
                switch (key.Modifiers)
                {
                case ConsoleModifiers.Control:
                    switch (key.Key)
                    {
                    case ConsoleKey.UpArrow:
                    case ConsoleKey.VolumeUp:
                        if (wavOut.Volume + 0.001f >= 1.0f)
                        {
                            wavOut.Volume = 1.0f;
                        }
                        else
                        {
                            wavOut.Volume += 0.001f;
                        }
                        break;

                    case ConsoleKey.DownArrow:
                    case ConsoleKey.VolumeDown:
                        if (wavOut.Volume - 0.001f <= 0.0f)
                        {
                            wavOut.Volume = 0.0f;
                        }
                        else
                        {
                            wavOut.Volume -= 0.001f;
                        }
                        break;

                    case ConsoleKey.LeftArrow:
                        p.Seek(currTS - 1);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.RightArrow:
                        p.Seek(currTS + 1);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.S:
                        if (speed - 0.01 <= 0.01f)
                        {
                            speed = 0.01;
                        }
                        else
                        {
                            speed -= 0.01;
                        }
                        changeRate();
                        break;

                    case ConsoleKey.F:
                        if (speed + 0.01 >= 4.0f)
                        {
                            speed = 4.0;
                        }
                        else
                        {
                            speed += 0.01;
                        }
                        changeRate();
                        break;
                    }
                    break;

                default:
                    switch (key.Key)
                    {
                    case ConsoleKey.UpArrow:
                    case ConsoleKey.VolumeUp:
                        if (wavOut.Volume + 0.01f >= 1.0f)
                        {
                            wavOut.Volume = 1.0f;
                        }
                        else
                        {
                            wavOut.Volume += 0.01f;
                        }
                        break;

                    case ConsoleKey.DownArrow:
                    case ConsoleKey.VolumeDown:
                        if (wavOut.Volume - 0.01f <= 0.0f)
                        {
                            wavOut.Volume = 0.0f;
                        }
                        else
                        {
                            wavOut.Volume -= 0.01f;
                        }
                        break;

                    case ConsoleKey.PageUp:
                        if (wavOut.Volume + 0.1f >= 1.0f)
                        {
                            wavOut.Volume = 1.0f;
                        }
                        else
                        {
                            wavOut.Volume += 0.1f;
                        }
                        break;

                    case ConsoleKey.PageDown:
                        if (wavOut.Volume - 0.1f <= 0.0f)
                        {
                            wavOut.Volume = 0.0f;
                        }
                        else
                        {
                            wavOut.Volume -= 0.1f;
                        }
                        break;

                    case ConsoleKey.LeftArrow:
                        p.Seek(currTS - 5d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.RightArrow:
                        p.Seek(currTS + 5d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D1:
                        p.Seek(60d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D2:
                        p.Seek(120d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D3:
                        p.Seek(180d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D4:
                        p.Seek(240d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D5:
                        p.Seek(300d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D6:
                        p.Seek(360d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D7:
                        p.Seek(420d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D8:
                        p.Seek(480d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D9:
                        p.Seek(540d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.D0:
                        p.Seek(600d);
                        bpcmWP.DropRingBuffer();
                        break;

                    case ConsoleKey.S:
                        if (speed - 0.1 <= 0.01f)
                        {
                            speed = 0.01;
                        }
                        else
                        {
                            speed -= 0.1;
                        }
                        changeRate();
                        break;

                    case ConsoleKey.D:
                        speed = 1f;
                        changeRate();
                        break;

                    case ConsoleKey.F:
                        if (speed + 0.1 >= 4.0f)
                        {
                            speed = 4.0;
                        }
                        else
                        {
                            speed += 0.1;
                        }
                        changeRate();
                        break;

                    case ConsoleKey.Home:
                        p.Seek(0);
                        break;

                    case ConsoleKey.Spacebar:
                        switch (wavOut.PlaybackState)
                        {
                        case PlaybackState.Playing:
                            wavOut.Pause();
                            break;

                        case PlaybackState.Paused:
                            wavOut.Play();
                            break;
                        }
                        break;

                    case ConsoleKey.Escape:
                    case ConsoleKey.Q:
                        Console.CursorTop -= 10;
                        exitNow();
                        break;
                    }
                    break;
                }
            }
            p = null;
        }