"synch safe integer"

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Benutzeravatar
Lincoln Six Echo
Beiträge: 138
Registriert: Di 26. Aug 2014, 16:42
OS, Lazarus, FPC: Win10, Debian
CPU-Target: I7/I9/Q9650/u.a.
Wohnort: Hamburg

"synch safe integer"

Beitrag von Lincoln Six Echo »

[Hat schon mal jemand mit synchsafe integer zu tun gehabt ?

Dazu der Artikel hier:
https://phoxis.org/2010/05/08/synch-safe/

Ich habe dazu nur etwas in C gefunden was ich nicht nachvollziehen kann, vielleicht kann es ja jemand übersetzen ?

Code: Alles auswählen

int synchsafe(int in)
{
	int out, mask = 0x7F;

	while (mask ^ 0x7FFFFFFF) {
		out = in & ~mask;
		out <<= 1;
		out |= in & mask;
		mask = ((mask + 1) << 8) - 1;
		in = out;
	}

	return out;
}

int unsynchsafe(int in)
{
	int out = 0, mask = 0x7F000000;

	while (mask) {
		out >>= 1;
		out |= in & mask;
		mask >>= 8;
	}

	return out;
}

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: "synch safe integer"

Beitrag von Mathias »

Ich habe die da ein paar Anhaltspunkte gegeben, ich hoffe dies hilft ein wenig weiter.
Oder kennst du C gar nicht ?

Code: Alles auswählen

int synchsafe(int in)
{
	int out, mask = 0x7F;  // $F7

	while (mask ^ 0x7FFFFFFF) {           // mask xor 0x7FFFFFFF
		out = in & ~mask;                   // and not
		out <<= 1;                               // out := out shl 1
		out |= in & mask;                   // out := out or in and mask
		mask = ((mask + 1) << 8) - 1;  // shl 8
		in = out;
	}

	return out;  // Exit(out);
}

int unsynchsafe(int in)
{
	int out = 0, mask = 0x7F000000;

	while (mask) {             // solange  mask <> 0
		out >>= 1;
		out |= in & mask;
		mask >>= 8;
	}

	return out;
}
Denke daran, "in" ist in Pascal ein reserviertes Wort.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Lincoln Six Echo
Beiträge: 138
Registriert: Di 26. Aug 2014, 16:42
OS, Lazarus, FPC: Win10, Debian
CPU-Target: I7/I9/Q9650/u.a.
Wohnort: Hamburg

Re: "synch safe integer"

Beitrag von Lincoln Six Echo »

Ersteinmal vielen Dank an Dich.

Wenn ich das richtig verstanden habe müsste es so sein:

a = In
b = Out
m = Mask

Code: Alles auswählen

      b := 0;
      m := $F7;
      while (m <> 0) do
      begin
        b := b shr 1;
        b := (b or a) and m;
        m  := m shr 8;
      end;  
Das wäre quasi das unsyncsafe aus dem C-Code.
Muss es nicht $7F sein bei 0x7FFFFFFFF ?

shokwave
Beiträge: 471
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: "synch safe integer"

Beitrag von shokwave »

Sorry wenn ich mich einmische, aber der Code sah mir noch fehlerhaft aus. So müsste es richtig sein, wenn ich mich nicht täusche.

Code: Alles auswählen

      b := 0;
      m := $F7;
      while (m <> 0) do
      begin
        b := b shr 1;
        b := b or (a and m); //erst das and von Input und Maske, dann das or mit dem Output
        m  := m shr 8;
      end;  
Lincoln Six Echo hat geschrieben:
Di 26. Sep 2023, 14:50
Das wäre quasi das unsyncsafe aus dem C-Code.
Muss es nicht $7F sein bei 0x7FFFFFFFF ?
Nein, der Algorithmus zum codieren geht vom letzten Byte zum ersten und braucht daher die Maske 00000000 0000000 00000000 01111111($7F). Die Abbruchbedingung für die Schleife ist, wenn die Maske so aussieht: 01111111 11111111 11111111 11111111($7FFFFFFF), also 3 mal um 8 Bit nach links verschoben und mit 1 aufgefüllt. Ich denke die entsprechende Zeile müsste so aussehen: mask := ((mask + 1) shl 8 ) - 1; Ein einfaches shl 8 "füllt" mit 0 auf.

Der Code zum decodieren geht andersrum von vorne nach hinten und braucht deswegen die Maske 01111111 00000000 00000000 00000000($7F000000). Die Abbruchbedingung ist, wenn die Maske gleich 0 ist, also 4 mal um 8 Bit nach rechts verschoben.

Ich hoffe das hilft dir weiter. Und falls ich mich vertan habe, bitte korrigieren.
mfg Ingo

Benutzeravatar
Lincoln Six Echo
Beiträge: 138
Registriert: Di 26. Aug 2014, 16:42
OS, Lazarus, FPC: Win10, Debian
CPU-Target: I7/I9/Q9650/u.a.
Wohnort: Hamburg

Re: "synch safe integer"

Beitrag von Lincoln Six Echo »

Leider liefern alle Versuche falsche Ergebnisse.

In dem Artikel wird es so erklärt:

So for example a 4 byte integer 0x000000FF whose binary representation is 00000000 00000000 00000000 11111111 will be represented as 00000000 00000000 00000001 01111111 in the synchronization safe format. If any of the MSB of a byte is 1, then it is shifted above on the next significant byte.

Gemacht wird das damit ein MP3 Codec diese bytes nicht für Audiodaten hält, da das Bit 7 immer 0 ist.

Also die vier byte des integer so bearbeiten das bit 7 = 0 ist und die evtl. 1 um eins nach links geschoben wird.

Trotzdem melden alle Programme Fehler "Bad Header" etc. weil die so kodierten / dekodierten integer falsche Werte liefern.

Lese ich die Tags aus einem Audio-File und dekodiere sie nach diesem Verfahren wird dann für eine 7 MB MP3 Datei die Länge von 63.568.935 GB ausgegeben was definitiv nicht stimmt.

Sehe ich den Wald vor lauter Bäumen nicht ? Hat jemand eine Idee dazu ?

Auch das hier liefert die gleichen falschen Ergebnisse:

Code: Alles auswählen

function DeCode(i : integer) : integer;
var
  bytes : array[0..3] of byte;
begin  
  move(i,bytes,4);
  bytes[0] := bytes[0] shl 21;
  bytes[1] := bytes[1] shl 14;
  bytes[2] := bytes[2] shl 7;
  move(bytes,i,4);
  result := i;
end;  

shokwave
Beiträge: 471
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: "synch safe integer"

Beitrag von shokwave »

Hab mal ein kleines Testprogramm geschrieben. Für mich sieht das decodieren richtig aus.

Code: Alles auswählen

program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes
  { you can add units after this }, StrUtils;

//Ausgabe eines Integer in Binär mit vorangestellter "Message" und in Klammern der Dezimalwert
procedure PrintInt(Message: String; AValue: Integer);
begin
  Write(Message);
  WriteLn(IntToBin(AValue, 64, 8), ' (', AValue, ')');
end;

//Umwandlung vom Synch-Save-Integer in einen normalen Integer
function SSIntToInt(Input:Integer): Integer;
var Mask, Output: Integer;
begin
  Output := 0;
  Mask := $7F000000;
  while (Mask <> 0) do
  begin
    Output := Output shr 1;
    Output := Output or (Input and Mask);
    Mask  := Mask shr 8;
  end;
  Result := Output;
end;

//Aufruf der Ausgabe vom Eingabewert und dem Ergebnis der Konvertierung
procedure TestConvert(Input: Integer);
begin
  PrintInt('Eingabe : ', Input);
  PrintInt('Ergebnis: ', SSIntToInt(Input));
  WriteLn();
end;

//Programm
begin
  TestConvert($017F);
  TestConvert($017F01);
  TestConvert($017F0101);
  TestConvert($017F7F);
  TestConvert($017F7F7F);

  ReadLn();
end.
Ausgabe ist:

Code: Alles auswählen

Eingabe : 00000000 00000000 00000001 01111111 (383)
Ergebnis: 00000000 00000000 00000000 11111111 (255)

Eingabe : 00000000 00000001 01111111 00000001 (98049)
Ergebnis: 00000000 00000000 01111111 10000001 (32641)

Eingabe : 00000001 01111111 00000001 00000001 (25100545)
Ergebnis: 00000000 00111111 11000000 10000001 (4178049)

Eingabe : 00000000 00000001 01111111 01111111 (98175)
Ergebnis: 00000000 00000000 01111111 11111111 (32767)

Eingabe : 00000001 01111111 01111111 01111111 (25132927)
Ergebnis: 00000000 00111111 11111111 11111111 (4194303)
mfg Ingo

Benutzeravatar
Lincoln Six Echo
Beiträge: 138
Registriert: Di 26. Aug 2014, 16:42
OS, Lazarus, FPC: Win10, Debian
CPU-Target: I7/I9/Q9650/u.a.
Wohnort: Hamburg

Re: "synch safe integer"

Beitrag von Lincoln Six Echo »

Ja das ist genau so wie es laut der Beschreibung sein soll.

Das Merkwürdige ist das es in der Anwendung falsche Werte liefert.

Ich habe das mit unzähligen MP3-Dateien ausprobiert.

Bei der einen kommt das Ergebnis der Size mit 36 byte (!) , bei der anderen (7.775 MB) das Ergebnis 63.556,398.213 byte.

In allen Specs die ich habe ist es aber genau so beschrieben wie in dem verlinkten Artikel.

Und will man auf die Website der ID3.org wird man nur darüber informiert das ein Server Error vorliegt und die Site nicht erreichbar ist...

Zum Indietischkantebeissen.....

shokwave
Beiträge: 471
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: "synch safe integer"

Beitrag von shokwave »

Hast du mal debuggt, was du aus der Datei ausliest, sprich welcher Wert in die Funktion rein kommt?

Ich bastle gerade am Auslesen vom Header und bin da schon auf ein Problemchen mit der Byteorder gestoßen.

Edit: Probier mal den Integer, bevor du ihn der Funktion übergibst, mit SwapEndian() umzuwandeln.
mfg Ingo

Benutzeravatar
Lincoln Six Echo
Beiträge: 138
Registriert: Di 26. Aug 2014, 16:42
OS, Lazarus, FPC: Win10, Debian
CPU-Target: I7/I9/Q9650/u.a.
Wohnort: Hamburg

Re: "synch safe integer"

Beitrag von Lincoln Six Echo »

Das scheint tatsächlich so zu sein das die Bytes "gedreht" sind.

In ID3v4 ist das wieder alles anders, TagScanner zeigt mir alles korrekt an, auch die Cover JPGs.

Bei MP3tag wird die selbe Datei als "Bad ID3v3 Header" angezeigt obwohl sie ID3v4 ist.

Was für ein Chaos...

Antworten