Gibt es Open-Source-C# -Code oder -Bibliothek, um eine grafische Wellenform bei einem Byte-Array darzustellen?Open-Source-C# -Code zur Darstellung der Wellenform?
Antwort
Dies ist als Open Source, wie es erhält:
Diese Funktion erzeugen in etwa sopublic static void DrawNormalizedAudio(ref float[] data, PictureBox pb,
Color color)
{
Bitmap bmp;
if (pb.Image == null)
{
bmp = new Bitmap(pb.Width, pb.Height);
}
else
{
bmp = (Bitmap)pb.Image;
}
int BORDER_WIDTH = 5;
int width = bmp.Width - (2 * BORDER_WIDTH);
int height = bmp.Height - (2 * BORDER_WIDTH);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Black);
Pen pen = new Pen(color);
int size = data.Length;
for (int iPixel = 0; iPixel < width; iPixel++)
{
// determine start and end points within WAV
int start = (int)((float)iPixel * ((float)size/(float)width));
int end = (int)((float)(iPixel + 1) * ((float)size/(float)width));
float min = float.MaxValue;
float max = float.MinValue;
for (int i = start; i < end; i++)
{
float val = data[i];
min = val < min ? val : min;
max = val > max ? val : max;
}
int yMax = BORDER_WIDTH + height - (int)((max + 1) * .5 * height);
int yMin = BORDER_WIDTH + height - (int)((min + 1) * .5 * height);
g.DrawLine(pen, iPixel + BORDER_WIDTH, yMax,
iPixel + BORDER_WIDTH, yMin);
}
}
pb.Image = bmp;
}
:
Diese
ein Array von Proben in Gleitkommaformat nimmt (wo Alle Abtastwerte liegen zwischen -1 und +1. Wenn Ihre ursprünglichen Daten tatsächlich in Form eines byte [] -Arrays vorliegen, müssen Sie ein wenig arbeiten, um es in float [] umzuwandeln. Lass es mich wissen, wenn du das auch brauchst.
aktualisieren: Da die Frage technisch etwas gebeten, ein Byte-Array zu machen, hier sind ein paar Hilfsmethoden:
public float[] FloatArrayFromStream(System.IO.MemoryStream stream)
{
return FloatArrayFromByteArray(stream.GetBuffer());
}
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length/4];
for (int i = 0; i < output.Length; i++)
{
output[i] = BitConverter.ToSingle(input, i * 4);
}
return output;
}
Update 2: Ich habe vergessen, es einen besseren Weg, dies zu tun ist :
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length/4];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
return output;
}
ich mit for
Schleifen nur so verliebt bin, denke ich.
Ich bin seit vielen Jahren ein Fan von ZedGraph und habe es verwendet, um alle Arten von Daten in verschiedenen Projekten anzuzeigen.
Der folgende Beispielcode Graphen, die einen Array aus Doppel zwischen -1 und 1 variierende:
void DisplayWaveGraph(ZedGraphControl graphControl, double[] waveData)
{
var pane = graphControl.GraphPane;
pane.Chart.Border.IsVisible = false;
pane.Chart.Fill.IsVisible = false;
pane.Fill.Color = Color.Black;
pane.Margin.All = 0;
pane.Title.IsVisible = false;
pane.XAxis.IsVisible = false;
pane.XAxis.Scale.Max = waveData.Length - 1;
pane.XAxis.Scale.Min = 0;
pane.YAxis.IsVisible = false;
pane.YAxis.Scale.Max = 1;
pane.YAxis.Scale.Min = -1;
var timeData = Enumerable.Range(0, waveData.Length)
.Select(i => (double) i)
.ToArray();
pane.AddCurve(null, timeData, waveData, Color.Lime, SymbolType.None);
graphControl.AxisChange();
}
Die obige Probe ahmt den Stil eines Audio-Editor durch die Achsen unterdrückt wird und die Farben zu ändern, die folgenden zu erzeugen:
in NAudio gibt es Code Audio-Wellenformen in beiden WinForms und WPF zu zeichnen. Sehen Sie sich die Demo-Projekte an, um Anwendungsbeispiele zu sehen.
Ich modifizierte MusiGenesis Lösung ein wenig. Diese gab mir ein viel besseres Ergebnis, vor allem mit Hausmusik :)
public static Bitmap DrawNormalizedAudio(List<float> data, Color foreColor, Color backColor, Size imageSize)
{
Bitmap bmp = new Bitmap(imageSize.Width, imageSize.Height);
int BORDER_WIDTH = 0;
float width = bmp.Width - (2 * BORDER_WIDTH);
float height = bmp.Height - (2 * BORDER_WIDTH);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(backColor);
Pen pen = new Pen(foreColor);
float size = data.Count;
for (float iPixel = 0; iPixel < width; iPixel += 1)
{
// determine start and end points within WAV
int start = (int)(iPixel * (size/width));
int end = (int)((iPixel + 1) * (size/width));
if (end > data.Count)
end = data.Count;
float posAvg, negAvg;
averages(data, start, end, out posAvg, out negAvg);
float yMax = BORDER_WIDTH + height - ((posAvg + 1) * .5f * height);
float yMin = BORDER_WIDTH + height - ((negAvg + 1) * .5f * height);
g.DrawLine(pen, iPixel + BORDER_WIDTH, yMax, iPixel + BORDER_WIDTH, yMin);
}
}
return bmp;
}
private static void averages(List<float> data, int startIndex, int endIndex, out float posAvg, out float negAvg)
{
posAvg = 0.0f;
negAvg = 0.0f;
int posCount = 0, negCount = 0;
for (int i = startIndex; i < endIndex; i++)
{
if (data[i] > 0)
{
posCount++;
posAvg += data[i];
}
else
{
negCount++;
negAvg += data[i];
}
}
posAvg /= posCount;
negAvg /= negCount;
}
+1 stimme ich voll und ganz zu! Danke für die Zugabe. Diese Methode gibt Wellenformen im Stil von SoundCloud.com. –
Schön gemacht! Danke für das Posten. – Reinaldo
@robyy Wie Bitmap DrawNormalizedAudio (Liste
mit angepassten Code von Robby und mit Graphics.Fill/DrawClosedCurve mit Anti-Aliasing, erhalte ich ein ziemlich gut aussehendes Ergebnis.
hier ist der Code:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Soundfingerprinting.Audio.Services
{
public static class AudioVisualizationService
{
public class WaveVisualizationConfiguration
{
public Nullable<Color> AreaColor { get; set; }
public Nullable<Color> EdgeColor { get; set; }
public int EdgeSize { get; set; }
public Nullable<Rectangle> Bounds { get; set; }
public double Overlap { get; set; }
public int Step { get; set; }
}
public static void DrawWave(float[] data, Bitmap bitmap, WaveVisualizationConfiguration config = null)
{
Color areaColor = Color.FromArgb(0x7F87CEFA);// Color.LightSkyBlue; semi transparent
Color edgeColor = Color.DarkSlateBlue;
int edgeSize = 2;
int step = 2;
double overlap = 0.10f; // would better use a windowing function
Rectangle bounds = Rectangle.FromLTRB(0, 0, bitmap.Width, bitmap.Height);
if (config != null)
{
edgeSize = config.EdgeSize;
if (config.AreaColor.HasValue)
areaColor = config.AreaColor.GetValueOrDefault();
if (config.EdgeColor.HasValue)
edgeColor = config.EdgeColor.GetValueOrDefault();
if (config.Bounds.HasValue)
bounds = config.Bounds.GetValueOrDefault();
step = Math.Max(1, config.Step);
overlap = config.Overlap;
}
float width = bounds.Width;
float height = bounds.Height;
using (Graphics g = Graphics.FromImage(bitmap))
{
Pen edgePen = new Pen(edgeColor);
edgePen.LineJoin = LineJoin.Round;
edgePen.Width = edgeSize;
Brush areaBrush = new SolidBrush(areaColor);
float size = data.Length;
PointF[] topCurve = new PointF[(int)width/step];
PointF[] bottomCurve = new PointF[(int)width/step];
int idx = 0;
for (float iPixel = 0; iPixel < width; iPixel += step)
{
// determine start and end points within WAV
int start = (int)(iPixel * (size/width));
int end = (int)((iPixel + step) * (size/width));
int window = end - start;
start -= (int)(overlap * window);
end += (int)(overlap * window);
if (start < 0)
start = 0;
if (end > data.Length)
end = data.Length;
float posAvg, negAvg;
averages(data, start, end, out posAvg, out negAvg);
float yMax = height - ((posAvg + 1) * .5f * height);
float yMin = height - ((negAvg + 1) * .5f * height);
float xPos = iPixel + bounds.Left;
if (idx >= topCurve.Length)
idx = topCurve.Length - 1;
topCurve[idx] = new PointF(xPos, yMax);
bottomCurve[bottomCurve.Length - idx - 1] = new PointF(xPos, yMin);
idx++;
}
PointF[] curve = new PointF[topCurve.Length * 2];
Array.Copy(topCurve, curve, topCurve.Length);
Array.Copy(bottomCurve, 0, curve, topCurve.Length, bottomCurve.Length);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillClosedCurve(areaBrush, curve, FillMode.Winding, 0.15f);
if (edgeSize > 0)
g.DrawClosedCurve(edgePen, curve, 0.15f, FillMode.Winding);
}
}
private static void averages(float[] data, int startIndex, int endIndex, out float posAvg, out float negAvg)
{
posAvg = 0.0f;
negAvg = 0.0f;
int posCount = 0, negCount = 0;
for (int i = startIndex; i < endIndex; i++)
{
if (data[i] > 0)
{
posCount++;
posAvg += data[i];
}
else
{
negCount++;
negAvg += data[i];
}
}
if (posCount > 0)
posAvg /= posCount;
if (negCount > 0)
negAvg /= negCount;
}
}
}
Das sieht ziemlich gut aus. – MusiGenesis
- 1. Werkzeug zur Darstellung der diagrammatischen Darstellung des c-Codes
- 2. BinaryString zur albabetischen Darstellung
- 3. Bevorzugtes Diagramm zur Darstellung der Web-Anwendungsinitialisierung
- 4. Verwendung von Vektor zur Darstellung der Matrix
- 5. TaskCompletionSource zur Darstellung von Async
- 6. Erstellen von Wellenform der Audiodatei in Android
- 7. Plotten von Positionsdaten zur Darstellung von Glätte
- 8. Sortierte Liste zur Vervollständigung der BST-Array-Darstellung
- 9. Regulärer Ausdruck zur Darstellung der Uhrzeit in einem speziellen Format
- 10. Java 8-Klasse zur Darstellung von Zeitintervallen
- 11. Eine Datenstruktur zur Darstellung buchbarer Zeitfenster
- 12. QTableView und ItemDelegate zur Darstellung eines Fortschrittsbalken
- 13. Clevere Datenstruktur zur Darstellung des geschichteten Kreises
- 14. Zeige Wellenform von Audio
- 15. Schnelle Anzeige der Wellenform in C/C++
- 16. Highcharts zur Darstellung in einer HTML-Tabelle
- 17. Immutable.js: Datenstruktur zur Darstellung des 2D-Spielfelds
- 18. Erstellen eines Baumes aus der linken Zeichenkette Darstellung der Darstellung
- 19. Wellenform-Visualisierung in Ruby
- 20. C# String-Darstellung der Methode
- 21. Gedruckte Darstellung der Liste
- 22. Visuelle Darstellung der Sätze
- 23. RDF-Darstellung der Sätze
- 24. Dreiecks-Wellenform-Array in Python
- 25. Audio-Wellenform-Visualisierung in schnellen
- 26. Datenstruktur zur Darstellung von Pfaden eines Baums ohne Redundanz
- 27. wie man die obere Kante der Wellenform gerundet
- 28. Ändern der Darstellung der Nummerierung der Latexabschnitte
- 29. Idiomatic Haskell Code zur Vereinfachung der Rekursion
- 30. Code zur Automatisierung der inkrementierten ZIP-Komprimierung?
Bis Sie es lizenzieren, und das OP 20 pro Gebrauch $ laden :) – Martin
@ Martin: Ich gebiete, dass nur für * suchen * auf sie. Wo sind meine 20 $? :) – MusiGenesis
Cooler Algorithmus. Ich habe gerade das nächste Sample mit meinem Pixel berechnet und einen Punkt dorthin gesetzt, aber die Maximal- und Minimalwerte des Pixelbereichs zu sehen, sieht viel besser aus! – andrewrk