¿Hay algún código de fuente abierta C# o biblioteca para presentar una forma de onda gráfica dada una matriz de bytes?¿Código de código abierto para presentar la forma de onda?
Respuesta
Esto es como código abierto como se pone:
public 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;
}
Esta función producirá algo como esto:
Esto toma una serie de muestras en formato de punto flotante (donde todos los valores de muestra van de -1 a +1). Si sus datos originales están realmente en forma de una matriz de bytes [], tendrá que trabajar un poco para convertirlos en flotantes []. Avíseme si lo necesita también.
actualización: puesto que la pregunta hecha técnicamente algo para rendir una matriz de bytes, aquí hay un par de métodos de ayuda:
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;
}
Actualización 2: Olvidé que hay una mejor manera de hacer esto :
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length/4];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
return output;
}
estoy tan enamorado de for
bucles, supongo.
He sido fan de ZedGraph durante muchos años y lo he usado para mostrar todo tipo de datos en varios proyectos.
El código de ejemplo representa gráficamente una serie de dobles que varía entre -1 y 1:
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();
}
Los anteriores imita muestra el estilo de un editor de audio mediante la supresión de los ejes y el cambio de los colores para producir el siguiente:
en NAudio, no hay código para dibujar las formas de onda de audio en WinForms y WPF. Echa un vistazo a los proyectos de demostración para ver ejemplos de cómo usarlo.
Modifiqué un poco la solución de MusiGenesis. Esto me dio un resultado mucho mejor, especialmente con la música house :)
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 Estoy completamente de acuerdo! thx para la adición. Este método proporciona formas de onda en el estilo de SoundCloud.com. –
¡Bien hecho! Gracias por publicar esto. – Reinaldo
@robyy Cómo llamar a Bitmap DrawNormalizedAudio (Lista
con código adaptado de Robby y el uso de Graphics.Fill/DrawClosedCurve con el antialiasing, aparece un resultado bastante bien.
aquí está el código:
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;
}
}
}
Esto se ve bastante bien. – MusiGenesis
- 1. Incluyendo código en proyectos de código abierto
- 2. Alternativa de código abierto para Drop Box
- 3. código abierto RTOS enlaces de código
- 4. OCR de código abierto
- 5. Código analizador de código abierto para el marcado Mediawiki
- 6. ¿Hay un repositorio de código abierto para código SQL?
- 7. ¿ExtJS es de código abierto?
- 8. Aplicaciones de código abierto para iPad
- 9. Donaciones para herramientas de código abierto
- 10. ¿Alternativa de código abierto para Mathworks Polyspace?
- 11. Analizador de código abierto OpenGL para Linux
- 12. la promoción de proyectos de código abierto
- 13. Código abierto para desarrollo de juegos Android
- 14. biblioteca zip de código abierto para .NET?
- 15. OCR de código abierto para árabe
- 16. OCR de código abierto para chino
- 17. Alternativa de código abierto para "Intellitrace"
- 18. GitHub para Windows: ¿es de código abierto?
- 19. Verificación ortográfica de código abierto
- 20. Alternativa de código abierto para listas de Sharepoint
- 21. ¿Es C de código abierto?
- 22. Meme Tracker de código abierto
- 23. F # proyectos de código abierto
- 24. Perfiladores de código abierto recomendados
- 25. dónde descargar para la base de código abierto de apple?
- 26. Delphi - proyectos de código abierto
- 27. Sistema experto de código abierto
- 28. de código abierto máquina virtual
- 29. ¿Hay máquinas en la nube (virtuales) disponibles de forma gratuita para las pruebas de código abierto?
- 30. Stemming - ejemplos de código o proyectos de código abierto
Hasta que autorizarla y cargar la OP $ 20 por el uso :) – Martin
@ Martin: Me carga que sólo para mirar * * en ella. ¿Dónde están mis $ 20? :) – MusiGenesis
algoritmo fresco. Solo estaba calculando la muestra más cercana a mi píxel y poniendo un punto allí, ¡pero haciendo el máximo y el mínimo del rango de ese píxel parece mucho mejor! – andrewrk