예제 #1
0
        // https://stackoverflow.com/questions/36081740/uwp-async-read-file-into-byte
        public static async Task <WaveData> LoadWave(StorageFile file)
        {
            byte[] wav;
            using (Stream stream = await file.OpenStreamForReadAsync())
            {
                using (var memoryStream = new MemoryStream())
                {
                    stream.CopyTo(memoryStream);
                    wav = memoryStream.ToArray();
                }
            }

            int channels      = wav[22];
            int sampleRate    = wav[24] + wav[25] * 256;
            int bitsPerSample = wav[34];
            int pos           = 12;

            while (!(wav[pos] == 100 && wav[pos + 1] == 97 && wav[pos + 2] == 116 && wav[pos + 3] == 97))
            {
                pos += 4;
                int chunkSize = wav[pos] + wav[pos + 1] * 256 + wav[pos + 2] * 65536 + wav[pos + 3] * 16777216;
                pos += 4 + chunkSize;
            }
            pos += 8;

            // Pos is now positioned to start of actual sound data
            int samples = (wav.Length - pos) / 2;   // 2 bytes per sample (16 bit sound mono)

            if (channels == 2)
            {
                samples /= 2;                       // 4 bytes per sample (16 bit stereo)
            }
            // Allocate memory (right will be null if only mono sound)
            var result = new WaveData
            {
                BitsPerSample = bitsPerSample,
                SampleRate    = sampleRate,
                LeftChannel   = new double[samples],
                RightChannel  = channels == 2 ? new double[samples] : null
            };

            int i = 0;

            while (pos < wav.Length)
            {
                result.LeftChannel[i] = WaveUtils.BytesToDouble(wav[pos], wav[pos + 1]);
                pos += 2;
                if (channels == 2)
                {
                    result.RightChannel[i] = WaveUtils.BytesToDouble(wav[pos], wav[pos + 1]);
                    pos += 2;
                }
                i++;
            }

            return(result);
        }
예제 #2
0
        public async Task LoadWave(string filePath)
        {
            var picker = new Windows.Storage.Pickers.FileOpenPicker();

            picker.FileTypeFilter.Add(".wav");
            var file = await picker.PickSingleFileAsync();

            var filename = file.Name;

            this.filenameTextBlock.Text = filename;

            this.Editor.WaveData = await WaveUtils.LoadWave(file);

            this.sampleRateTextBlock.Text = $"{this.Editor.WaveData.SampleRate.ToString()} Hz";
            this.formatTextBlock.Text     = $"{this.Editor.WaveData.BitsPerSample.ToString()}-bit";
        }
예제 #3
0
        // https://stackoverflow.com/questions/39605118/how-to-draw-an-audio-waveform-to-a-bitmap
        private void canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
        {
            if (Editor.WaveData.LeftChannel == null)
            {
                return;
            }

            const int FONT_SIZE = 14;

            args.DrawingSession.Clear(sender.ClearColor);
            args.DrawingSession.Antialiasing = Microsoft.Graphics.Canvas.CanvasAntialiasing.Aliased;
            var textFormat = new CanvasTextFormat {
                FontSize = FONT_SIZE, Direction = CanvasTextDirection.TopToBottomThenLeftToRight
            };
            var negTextFormat = new CanvasTextFormat {
                FontSize = FONT_SIZE, Direction = CanvasTextDirection.BottomToTopThenLeftToRight
            };

            var scale  = Editor.Scale;
            var size   = Editor.WaveData.LeftChannel.Length;
            var height = sender.ActualHeight;
            var width  = sender.ActualWidth * scale;

            float previousX = 0;
            float previousY = (float)(height / 2);

            for (int x = 0; x < width / scale; x++)
            {
                int start = (int)(x * (size / width));
                int end   = (int)((x + 1) * (size / width));
                if (end > size)
                {
                    end = size;
                }

                if (start == end)
                {
                    // Blank pixel
                    continue;
                }

                WaveUtils.averages(Editor.WaveData.LeftChannel, start, end, out double posAvg, out double negAvg);

                float yMax = (float)(height - ((posAvg + 1) * .5f * height));
                float yMin = (float)(height - ((negAvg + 1) * .5f * height));

                args.DrawingSession.DrawLine(x, yMax, x, yMin, Colors.Red);

                if (posAvg > 0)
                {
                    args.DrawingSession.DrawText(posAvg.ToString(), x - FONT_SIZE / 2, yMin, Colors.Blue, textFormat);
                    args.DrawingSession.DrawLine(previousX, previousY, x, yMax, Colors.Silver);
                    previousY = yMax;
                }
                else if (negAvg < 0)
                {
                    args.DrawingSession.DrawText(negAvg.ToString(), x - FONT_SIZE / 2, yMax, Colors.Blue, negTextFormat);
                    args.DrawingSession.DrawLine(previousX, previousY, x, yMin, Colors.Silver);
                    previousY = yMin;
                }
                else
                {
                    args.DrawingSession.DrawText("0", x - FONT_SIZE / 2, yMin, Colors.Blue, textFormat);
                    previousY = (float)(height / 2);
                }

                previousX = x;
            }

            // Selection
            if (this.Editor.PointerX1 > 0)
            {
                args.DrawingSession.DrawLine((float)this.Editor.PointerX1, 0f, (float)this.Editor.PointerX1, (float)height, Colors.Blue);
            }
            if (this.Editor.PointerX2 > 0)
            {
                args.DrawingSession.DrawLine((float)this.Editor.PointerX2, 0f, (float)this.Editor.PointerX2, (float)height, Colors.Blue);
            }

            if (this.Editor.IsPointerPressed)
            {
                var brush = new CanvasSolidColorBrush(canvas, Colors.LightSkyBlue);
                brush.Opacity = 0.4f;
                args.DrawingSession.FillRectangle((float)this.Editor.PointerX1, 0f, (float)(this.Editor.PointerX2 - this.Editor.PointerX1), (float)height, brush);
            }
        }