Esiste un codice o libreria C# open source per presentare una forma d'onda grafica data una matrice di byte?Codice sorgente C# aperto per presentare la forma d'onda?
risposta
Questo è come open source come ottiene:
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;
}
Questa funzione produrrà qualcosa di simile:
Ciò richiede una serie di campioni in formato in virgola mobile (dove tutti i valori campione vanno da -1 a +1). Se i tuoi dati originali sono in realtà sotto forma di una matrice di byte [], dovrai fare un po 'di lavoro per convertirli in float []. Fammi sapere se ne hai bisogno anche tu.
Aggiornamento: dal momento che la questione tecnicamente chiesto qualcosa per rendere un array di byte, qui ci sono un paio di metodi helper:
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: Ho dimenticato che c'è un modo migliore per fare questo :
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length/4];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
return output;
}
sono così innamorata di for
loop, immagino.
Sono stato un fan di ZedGraph per molti anni e l'ho usato per visualizzare tutti i tipi di dati in vari progetti.
Il seguente codice di esempio Grafici una serie di doppie variabile tra -1 e 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();
}
L'esempio simula sopra lo stile di un editor audio sopprimendo gli assi e cambiando i colori per produrre il seguente:
in NAudio, c'è il codice per disegnare le forme d'onda audio in entrambe le WinForms e WPF. Dai un'occhiata ai progetti demo per esempi su come usarlo.
Ho modificato un po 'la soluzione di MusiGenesis. Questo mi ha dato un risultato molto migliore, soprattutto con la musica 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 Sono completamente d'accordo! grazie per l'aggiunta. Questo metodo fornisce forme d'onda nello stile di SoundCloud.com. –
Ben fatto! Grazie per aver postato questo. – Reinaldo
@robyy Come chiamare la funzione Bitmap DrawNormalizedAudio (Elenco
con il codice adattato da Robby e utilizzando Graphics.Fill/DrawClosedCurve con antialiasing, ottengo un buon risultato cercando.
Ecco il codice:
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;
}
}
}
Questo sembra abbastanza buono. – MusiGenesis
- 1. forma jQuery presentare
- 2. Impossibile compilare codice sorgente aperto cv 2.3.1
- 3. forma jQuery presentare vs document.form.submit
- 4. C codice sorgente libreria
- 5. Serve download dopo forma presentare w/validazione
- 6. come presentare forma come oggetto JSON
- 7. Grammatica C nel codice sorgente GCC
- 8. dove trovare il codice sorgente per la libreria standard C++
- 9. Beautifier codice sorgente per C++ (vC++)?
- 10. Buon browser di codice sorgente per C
- 11. Combina caricamento delle immagini ajax con la forma presentare ajax
- 12. angolare - ingresso forma chiara dopo presentare
- 13. come convalidare il modello in forma presentare
- 14. Esistono strumenti per trasformare il codice sorgente in C++ nel codice sorgente in C/C++, ma con modelli istanziati (srotolati)?
- 15. Esempi di codice sorgente SharpSvn e C#
- 16. Codice sorgente per app Android?
- 17. Codice sorgente C in documento Latex
- 18. parsing del codice sorgente C++ nell'ambiente java
- 19. Come fermare una forma di presentare durante l'esecuzione di codice a barre scanner
- 20. Perché C# genera EXE diversi per lo stesso codice sorgente?
- 21. ottenere riferimento alla finestra di destinazione _blank sulla forma presentare
- 22. dov'è il codice sorgente C++ filt?
- 23. Codice sorgente per la nuova app Calendario Lollipop per Android
- 24. Codice sorgente Python per operatore "in" incorporato
- 25. Codice sorgente per l'algoritmo di Xiaolin Wu in C?
- 26. Codice sorgente offuscamento
- 27. Codice sorgente PHP per funzioni integrate
- 28. Come associare oggetto sottoclasse in forma primavera presentare come modelAttribute
- 29. VS Codice aperto ultimi file
- 30. mostra il codice sorgente per la funzione in R
Fino a quando si licenza, e caricare il PO di $ 20 per l'uso :) – Martin
@ Martin: mi carica che solo per guardare * * a questo. Dove sono i miei $ 20? :) – MusiGenesis
Algoritmo freddo. Stavo solo calcolando il campione più vicino al mio pixel e mettendo un punto lì, ma facendo il massimo e il minimo dell'intervallo di quel pixel sembra molto meglio! – andrewrk