Laden...

bytearray SCHNELL in intarray konvertieren

Erstellt von thefiloe vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.576 Views
T
thefiloe Themenstarter:in
87 Beiträge seit 2010
vor 12 Jahren
bytearray SCHNELL in intarray konvertieren

Das Problem das ich habe ist, dass ich einen eigenen Stream habe aus welchem gelesen wird und welcher die gelesenen bytes zur Laufzeit in ein intarray konvertieren soll und einem event übergeben.

Der Sinn der ganzen Sache ist, dass es ein Audiostream ist aus welchem ein Callback liest. Für gewisste Sachen brauch ich jedoch die soeben gelesen bytes als int (z.b für eine visualisierung)

        public int Read(byte[] buffer, int offset, int count)
        {
            int read = source.Read(buffer, offset, count);
            return read;
        }

So sieht das Ganze bis jetzt aus. Er liest halt wiederum aus einem anderen Stream (können mehrere Streams aneinander gehängt werden). Nun ist meine Frage halt wie könne ich hier SCHNELL den buffer in ein intarray konvertieren und anschließend an ein Event übergeben?
2. Frage ist ein Event Sinnvoll um so große Mengen an Daten hin und her zu schieben? oder gibt es eine alternative. Denn bedenkte die Daten sind im PCM Format also nicht mehr als mp3 kompremiert oder was auch immer. Das hat zur Folge, dass teilweise 176400Bytes und mehr pro Sekunde durch den Stream fließen.

Also dachte ich, ich Frage mal euch ob ihr eine performante Lösung wisst.

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

was soll genau passieren bei der Konvertierung? Sollen Bytes auch zu Integerwerten zusammengefasst werden oder gehts nur darum den gleichen Wert einmal als Integer und einmal als Byte zu haben?

Zu den Events: Völlig egal wie groß die Arrays sind, du übergibst ja nur die Referenz darauf. Aber, man sollte natürlich schon darauf achten nicht mit jedem Event nen neues Array zu erstellen (dann fallen natürlich massig Speicherallokierungen an) sondern das alte wiederzuverwenden wenn möglich.

Baka wa shinanakya naoranai.

Mein XING Profil.

1.346 Beiträge seit 2008
vor 12 Jahren

Ich habe mir für sowas nen kleinen Hack gebaut. Ob es das performanteste oder beste ist um sowas zu machen weis ich nicht. PCM Daten sollten doch aber shorts sein(?) Genau für sowas hab ich das nämlich gebaut. Für integers kannst du das aber genau so umbauen

    /// <summary>
    /// You must not use Array.Length! Use AudioBuffer.GetLength instead.
    /// </summary>
    [StructLayout(LayoutKind.Explicit, Pack=2)]
    public class AudioBuffer
    {
        [FieldOffset(0)]
        int _length;
        
        [FieldOffset(8)]
        byte[] _byteBuffer;

        [FieldOffset(8)]
        short[] _shortBuffer;

        public AudioBuffer(byte[] allocate)
        {
            if (allocate == null)
                throw new ArgumentNullException("allocate");
            if (allocate.Length % sizeof(short) != 0)
                throw new ArgumentOutOfRangeException("allocate");
            _byteBuffer = allocate;
        }

        public byte[] ByteBuffer { get { return _byteBuffer; } }
        public short[] ShortBuffer { get { return _shortBuffer; } }

        public int GetLength()
        {
            return _byteBuffer.Length /  sizeof(short);
        }
    }

Wichtig dabei ist, dass du ShortBuffer.Length nicht benutzt, sonodern Die GetLength Methode. Sonst bekommst du eine falsche Länge

//Edit Blöd wenn man beim kurzen Überarbeiten des Codes Fehler einbaut

C
2.121 Beiträge seit 2010
vor 12 Jahren

Ich würde da gnadenlos böse mit Pointern arbeiten wenns wirklich fix gehen soll.
Aber die Idee über mir sieht auch cool aus, ich denk mal da ist auch kein Verlust drin.

T
thefiloe Themenstarter:in
87 Beiträge seit 2010
vor 12 Jahren

es soll schon die bytes zusammenfassen.
Außerdem das mit eine mit den offsets hatte ich schon. Funktioniert aber nicht so gut, da ich dort bei sachen wie .Length exceptions bekomme (wieos kp).
An pointer hatte ich auch gedacht nur leider habe ich auf dem gebiet weniger erfahrung.

hatte es mal ca. so versucht:


int* i = (int*)&byteArray;

Klappt aber nicht von dem her wäre ich froh wenn mir jemand sagen könnte wie das mit unsafe gelöst werden kann 😃

C
2.121 Beiträge seit 2010
vor 12 Jahren

Was heißt zusammenfassen? Wie das ausgelesen wird ist ja nur Definitionssache.
Du schreibst Bytes in den Speicher, der erst mal als Folge von einzelnen Bytes gesehen wird. Dann liest du int aus, davon gibts natürlich nur 1/4 so viele.
Zu fixed und unsafe schaust du am besten in die Hilfe, die ist besser als ich 😃

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

es soll schon die bytes zusammenfassen.
Außerdem das mit eine mit den offsets hatte ich schon. Funktioniert aber nicht so gut, da ich dort bei sachen wie .Length exceptions bekomme (wieos kp). Dann würde ich schon den Weg wie von pdelvo vorgeschlagen, nutzen. Man muss halt den Wert von Pack entsprechend anpassen (sprich hier 1). Wenn du Length vom Byte Array aufrufst, gibt das dann natürlich einen falschen Wert. Wieso hat ja chilic geschrieben und ansonsten hat pdelvo das ja schon richtig im Code drin. Ansonsten gilt wie immer natürlich [Hinweis] Wie poste ich richtig? Punkt 5. "Es kommt ne Exception" ist keine Fehlerbeschreibung.

Baka wa shinanakya naoranai.

Mein XING Profil.

309 Beiträge seit 2008
vor 12 Jahren

Hmm,

genau, was heißt "Integer sollen die Bytes zusammenfassen"?

byte = 8bit = 1 byte (ach nee 😉 )
Int = 32bit = 4 byte

Also wenn du z.b. 4 bytes (0xfa, 0xff, 0x1d, 0x42) hast soll dann der Integer den Wert 0x421dfffa oder 0xfaff1d42 (Achtung auf die Bytereihenfolge (Endianess)!) haben?
Auch aufpassen musst du das der größtmögliche Wert eines Ints (Int.MaxValue) 0x7fffffff und nicht 0xffffffff beträgt. So ist 0xafffffff z.B. nicht definiert. Wenn du aber einfach 4 Bytes so zusammenfasst kann dieser Wert leicht herauskommen.

Bist du dir wirklich sicher das du aus den einzelnen Byte werten nicht einzelne Integer Werte machen willst.

Ach ja:
Wenns wirklich, wirklich, wirklich auf ganz, ganz fixe Art gehen soll, schreib die Konvertierungsfunktion in nativem C und binde die DLL per Interop wieder in C# ein. 😁
Call by Reference und Pointerarithmetik heißen die Zauberworte! :evil:

using System;class H{static string z(char[]c){string r="";for(int x=0;x<(677%666);x++)r+=c[
x];return r;}static void Main(){int[]c={798,218,229,592,232,274,813,585,229,842,275};char[]
b=new char[11];for(int p=0;p<((59%12));p++)b[p]=(char)(c[p]%121);Console.WriteLine(z(b));}}

1.361 Beiträge seit 2007
vor 12 Jahren

Hi,

ich wuerde einfach Buffer.BlockCopy nutzen. Und erst wenn echte Profiler-Ergebnisse dies als Bottleneck herausstellen, mich weiter damit beschaeftigen. (Und mich dann Pointern, FieldOffsets, etc. widmen)

Natuerlich behaelst du ein und das selbe int-Array und erzeugst nicht jedesmal ein neues.

beste Gruesse
zommi

1.346 Beiträge seit 2008
vor 12 Jahren

0xafffffff ist definiert, und zwar als -1342177281. Und schneller bekommt man mMn aus einem Byte Array kein Integer Array. Mein Code hat den Vorteil, das nichts kopiert wird, und das das Zurückkonvertieren, wie das hinkonverteren keine Resourcen kostet. Um Audio Daten zu bearbeiten hat es sich bei mir als Vorteilhaft gezeigt. Ich konnte in meinem Fall mit den Shorts schnell arbeiten und hatte die Daten sofort wieder als byte Array zum weiterschicken

T
thefiloe Themenstarter:in
87 Beiträge seit 2010
vor 12 Jahren

Wenn ich mich noch errinneren könnte was die Exception war hätte ich das natürlich gesagt. Vll war es auch keine Exception ich weiß nur soviel, dass es einen Fehler gab (hatte das schon ausprobiert). Ich werd das aber nochmal schnell implementiern, da ich eh schon eine ähnliche Klasse habe und falls es dann immernoch Probleme gibt melde ich mich nochmal 🙂

Und ja es ist mir bewusst, dass im speicher bytes liegen und es ist mir auch bewusst dass ein short 2 byte hat und ein int 4 bytes 🙂

aba danke nochma 🙂

EDIT:
ok habs am Ende doch noch hinbekommen. Ist ne Mischung zwischen unsafe und der offset methode geworden (konnte den floatbuffer ausbauen 🙂 ) aba danke nochma und so siehts aus: =) =)