Verlustbehaftet oder verlustfrei?

18

Bestimmen Sie anhand einer Audiodatei, ob diese in einem verlustbehafteten oder einem verlustfreien Format codiert ist. Für diese Herausforderung müssen nur die folgenden Formate klassifiziert werden:

Regeln

  • Wenn die Eingabe in Form eines Dateinamens erfolgt, sollten keine Annahmen über den Dateinamen getroffen werden (z. B. kann nicht garantiert werden, dass die Erweiterung für das Format korrekt ist oder sogar vorhanden ist).
  • In den Eingabedateien sind keine ID3- oder APEv2-Metadaten vorhanden.
  • Beliebige zwei eindeutige und unterscheidbare Ausgaben können verwendet werden, wie z. B. 0und 1, lossyund lossless, foound barusw.

Testfälle

Die Testfälle für diese Herausforderung bestehen aus einer ZIP-Datei , die zwei Verzeichnisse enthält: lossyund lossless. Jedes Verzeichnis enthält mehrere Audiodateien, die alle 0,5-Sekunden-440-Hz-Sinuswellen sind und in verschiedenen Formaten codiert sind. Alle Audiodateien haben Erweiterungen, die den oben genannten Formaten entsprechen, mit Ausnahme von A440.m4a(AAC-Audio in einem MPEG Layer 4-Container).

Mego
quelle
" AAC-Audio in einem MPEG-Layer-4-Container " wirft die Frage auf: Welche anderen Containerformate müssen Antworten verarbeiten?
Peter Taylor
@PeterTaylor Nur AAC wurde besonders erwähnt, da ich keine Möglichkeit gefunden habe, AAC-Audio bereitzustellen, ohne es über FFMPEG in einen MPEG-Layer-4-Container einzubetten. Das Vorbis-Audio ist in einen Ogg-Container eingebettet (wie es für Vorbis-Audio üblich ist). Alle anderen sind Standalone-Formate.
Mego
Sind Sie sich über die TTA-Datei sicher? Laut Spezifikation sollten TTA-Dateien mit der magischen Nummer TTA1 oder TTA2 beginnen. FFM2 (die magische Nummer Ihrer Datei) scheint dem FFmpeg-Stream zu entsprechen. Die Linux- Datei erkennt den TTA1-Header, nicht jedoch den FFM2-Header.
Dennis
Können wir auch annehmen, dass sich AAC immer in einem MPEG Layer 4-Header befindet? Wenn nicht, was können wir davon ausgehen?
Dennis
Können wir den Inhalt der Datei als Eingabe nehmen oder muss unser Code sie abrufen?
Shaggy

Antworten:

18

Gelee , 7 5 Bytes

ƈƈeØA

Verlustbehaftete Formate geben 0 zurück , verlustfreie Formate geben zurück 1 zurück .

Probieren Sie es online! (Permalinks in Gist)

Hintergrund

Die Formate, die wir unterstützen müssen, haben die folgenden magischen Zahlen, dh sie beginnen mit diesen Bytes.

Format    Header (text)       Header (hex)
-----------------------------------------------------------------------------------
AC3       .w                  0B 77
AMR       #!AMR               23 21 41 4D 52
AAC       ÿñP@..ü             FF F1 50 40 00 1F FC
  M4A     ... ftypM4A         00 00 00 20 66 74 79 70 4D 34 41 20
MP2       ÿû                  FF FB
MP3       ÿû                  FF FB
OGG       OggS                4F 67 67 53
WMA       0&²u.fÏ.¦Ù.ª.bÎl    30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C

AIFF      FORM????AIFF        46 4F 52 4D ?? ?? ?? ?? 41 49 46 46
FLAC      fLaC                66 4C 61 43
TTA       TTA1                54 54 41 31
  FFM2    FFM2                46 46 4D 32
WAV       RIFF????WAVE        52 49 46 46 ?? ?? ?? ?? 57 41 56 45

Eingezogene Einträge sind Container für das vorhergehende Format, die in den Testfällen angezeigt werden. ?bezeichnet ein variables Byte..bezeichnet ein nicht druckbares Byte. Alle anderen Bytes werden als ISO 8859-1-Zeichen angezeigt.

Indem wir uns nur das zweite Byte ansehen, können wir das Format auf einfache Weise bestimmen:

Verlustfreie Formate haben einen Großbuchstaben als zweites Byte, verlustbehaftete Formate nicht.

Wie es funktioniert

ƈƈeØA  Main link. No arguments.

ƈ      Read a char from STDIN and set the left argument to this character.
 ƈ     Read another char from STDIN and set the return value to this character.
   ØA  Yield the uppercase alphabet, i.e., "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
  e    Exists; return 1 if the return value (second char on STDIN) belongs to the
       uppercase alphabet, 0 if not.
Dennis
quelle
2
Dies ist eine sehr clevere Lösung.
Mego
10

C 82 80 32 Bytes

Inspiriert von der Antwort von @Dennis , kann dies noch viel weiter reduziert werden:

main(){return getchar()&200^64;}

Leiten Sie die Dateidaten an stdin. Gibt 0 für verlustfrei oder ungleich Null für verlustbehaftet zurück.

Oder der ursprüngliche längere Scheck:

char v[5];main(){scanf("%4c",v);return*v&&strstr("fLaC FORM RIFF TTA1 FFM2",v);}

Leiten Sie die Dateidaten an stdin. Gibt einen Wert ungleich Null (1) für verlustfrei oder 0 für verlustreich zurück.

Soweit ich weiß, haben alle von Ihnen aufgelisteten Formate separate magische Zahlen (außer AIFF / WAV, aber beide sind trotzdem verlustfrei), so dass diese magische Zahl nur auf einen bekannten verlustfreien Wert überprüft wird. Dies *v&&dient nur zum Schutz vor übereinstimmenden Dateien, die mit einem Null-Byte (M4A) beginnen.

Ich habe die Werte, die ich in den technischen Datenblättern ( fLaC= FLAC, RIFF= WAV / AIFF, TTA1= TTA) und gefunden habe, aufgenommenFORM = AIFF und FFM2= TTA gefunden habe, stammen aus den bereitgestellten Beispieldateien (ich kann nur vermuten, dass es sich um Wrapperformate oder spätere Versionen handelt).


Oder eine kürzere Alternative zum Betrügen:

Bash + Datei, 61 Bytes

N="$(file "$1")";[[ $N = *": d"* || $N = *IF* || $N = *FL* ]]

Nimmt den Dateinamen als Argument. Gibt 0 für verlustfrei oder ungleich Null für verlustbehaftet zurück.

Tut genau das, was Sie erwarten würden; fragt nach filedem Dateityp und sucht dann nach bekannten Mustern. TTA-Übereinstimmungen : d( : data), AIFF / WAV-Übereinstimmungen IFund FLAC-Übereinstimmungen FL. Keines der verlustfreien Ergebnisse stimmt mit einem dieser Ergebnisse überein, und ich habe getestet, dass es immer noch funktioniert, wenn die Dateinamen entfernt werden.


Testen:

for f in "$@"; do
    echo "Checking $f:";
    ./identify2 "$f" && echo "shorter C says LOSSLESS" || echo "shorter C says LOSSY";
    ./identify < "$f" && echo "longer C says LOSSY" || echo "longer C says LOSSLESS";
    ./identify.sh "$f" && echo "file says LOSSLESS" || echo "file says LOSSY";
done;

# This can be invoked to test all files at once with:
./identify_all.sh */*
Dave
quelle
Funktioniert Ihre Bash-Lösung auch, wenn die Dateierweiterung falsch ist? "Es wird nicht garantiert, dass die Erweiterung für das Format korrekt ist", daher sollten Sie in der Lage sein, einer Datei eine falsche Erweiterung zuzuweisen und sie dennoch funktionieren zu lassen.
mbomb007
@ mbomb007 Ich habe gerade getestet, dass die Erweiterungen vertauscht sind und sie trotzdem gut identifiziert werden. Ich glaube, ich filetraue Erweiterungen sowieso nicht (viele Benutzer, die ein PNG in ein JPEG umbenennen, ist dasselbe wie es zu konvertieren!)
Dave
7

GS2 , 3 Bytes

◄5ì

Verlustbehaftete Formate geben 0 zurück , verlustfreie Formate geben 1 zurück .

Probieren Sie es online!(Permalinks in Gist)

Hintergrund

Die Formate, die wir unterstützen müssen, haben die folgenden magischen Zahlen, dh sie beginnen mit diesen Bytes.

Format    Header (text)       Header (hex)
-----------------------------------------------------------------------------------
AC3       .w                  0B 77
AMR       #!AMR               23 21 41 4D 52
AAC       ÿñP@..ü             FF F1 50 40 00 1F FC
  M4A     ... ftypM4A         00 00 00 20 66 74 79 70 4D 34 41 20
MP2       ÿû                  FF FB
MP3       ÿû                  FF FB
OGG       OggS                4F 67 67 53
WMA       0&²u.fÏ.¦Ù.ª.bÎl    30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C

AIFF      FORM????AIFF        46 4F 52 4D ?? ?? ?? ?? 41 49 46 46
FLAC      fLaC                66 4C 61 43
TTA       TTA1                54 54 41 31
  FFM2    FFM2                46 46 4D 32
WAV       RIFF????WAVE        52 49 46 46 ?? ?? ?? ?? 57 41 56 45

Eingezogene Einträge sind Container für das vorhergehende Format, die in den Testfällen angezeigt werden. ?bezeichnet ein variables Byte. .bezeichnet ein nicht druckbares Byte. Alle anderen Bytes werden als ISO 8859-1-Zeichen angezeigt.

Indem wir uns nur das zweite Byte ansehen, können wir das Format auf einfache Weise bestimmen:

Verlustfreie Formate haben einen Großbuchstaben als zweites Byte, verlustbehaftete Formate nicht.

Wie es funktioniert

     (implcit) Push the entire input from STDIN as a string on the stack.
◄    Push 1.
 5   Get the strings character at index 1, i.e., its second character.
  ì  Test if the character is an uppercase letter.
Dennis
quelle
2

JavaScript (ES6), 20 Byte

c=>/^[fFRT]/.test(c)

Erläuterung

Nimmt den Inhalt der Datei als eine Eingabe und gibt , truewenn die Datei lossless ist oder falsewenn es mit Verlust behaftete durch Testen der ersten Zeichen dieser Eingabe , um zu sehen , ob es eine ist f, F, Roder T.


Versuch es

Fügen Sie den Inhalt einer Datei in das ein textarea.

f=
c=>/^[fFRT]/.test(c)
i.addEventListener("input",_=>console.log(f(i.value)))
<textarea id=i></textarea>


Zweiter Versuch, 81 63 Bytes

Ruft den Inhalt einer Datei von einer angegebenen URL ab, was sich als überflüssig herausstellte.

u=>fetch(u).then(r=>r.text()).then(t=>alert(/^[fFRT]/.test(t)))

Erster Versuch, 146 116 89 Bytes

Ungültige MIME-Typen sind an Erweiterungen gebunden, und Antwortheader gelten anscheinend als zusätzliche Eingabe.

u=>fetch(u).then(r=>alert(/aiff|flac|tta|wave|wav$/.test(r.headers.get("Content-Type"))))
Zottelig
quelle
Webserver generieren normalerweise das MIME basierend auf der Dateierweiterung, was hier gegen die Regeln verstößt. Haben Sie überprüft, ob es bei Dateien ohne Dateierweiterung funktioniert? (Wenn dies der Fall ist, sollten Sie wahrscheinlich den Namen des Servers angeben, den Sie als Teil der "Sprache" verwenden.)
Dave,
1
@ Dave Ziemlich sicher, dass sie es nicht tun. MIME und Extension sind überhaupt nicht voneinander abhängig. Wenn Sie die Dateierweiterung ändern und hochladen, ist der MIME-Typ der MIME-Wert des tatsächlichen Inhalts der Datei und nicht der Erweiterung. Da dies der Fall ist, ist die Eingabe als URL wahrscheinlich nicht zulässig. Ich bin mir nicht sicher.
mbomb007
@ mbomb007 Ich bin mir nicht sicher, warum du das sagst. MIME-Typen sind eine Internet-Sache, keine Dateisystem- / Dateisache, und die Server, die mir bekannt sind, bestimmen sie anhand der Erweiterung mithilfe einer konfigurierten Suche (um die Geschwindigkeit der Bereitstellung von Headern zu ermitteln). Sie möchten nicht jede Datei vor der Bereitstellung überprüfen es). Nehmen Sie zum Beispiel Apache AddType <mime> <extension>oder IIS <MimeMap>. Natürlich könnte ein bestimmtes Setup- oder Datei-Hosting-Tool eine ordnungsgemäße Überprüfung durchführen, und das wäre es wert, wenn die Serverauswahl Teil der Antwort wäre (da der Server den Dateityp bestimmt!)
Dave,
1
Ich habe die Dateiüberprüfung mit .NET durchgeführt und der MIME-Typ stimmte mit dem Inhalt überein, auch wenn die Erweiterung vor dem Hochladen geändert wurde.
mbomb007
@ mbomb007 In diesem Fall muss die von Ihnen verwendete .NET-Komponente entweder während des Uploads oder beim Bereitstellen der Dateien eine Dateiprüfung durchgeführt haben (ich würde es beim Upload für die Leistung erraten, aber Sie wissen es nie). Wenn wir also zu meinem ursprünglichen Kommentar zurückkehren, würde dies zu einer Antwort wie "JavaScript + .NET SeverLibraryXYZ" führen. Was die Eingabe von einer URL angeht, kann ich sehen, warum Sie zögern, aber ich persönlich würde es für gültig halten, solange die Serverauswahl erwähnt wird. Vielleicht gibt es ein vorhandenes Meta, aber letztendlich liegt es natürlich an Mego.
Dave
1

Chip , 11 Bytes

~Z~S
t'G~aF

Schamlos wiederholte Dennis 'Jelly-Antwort in Chip.

Verlustfreie Renditen 0x0, verlustreiche Renditen 0x1.

Probieren Sie es online aus , Links in Kürze (danke Dennis für die TIO-Strategie hier)

Erklären!

~Z~S
t'

Dieser Teil ist hauswirtschaftlich: Er setzt Sdas erste Byte taußer Kraft und endet nach dem zweiten.

G~aF

Das ist das Fleisch der Entscheidung. Auf jedes Eingangsbyte wird von den Bits zugegriffen HGFEDCBA. Wenn Ggesetzt ist und Fnicht, bedeutet dies, dass das Byte im Bereich von 0x40bis liegt0x5f (was in etwa 'Großbuchstaben' entspricht und für die jeweilige Aufgabe gut genug ist).

Aus Gründen der Byte-Ersparnis kehre ich diese Entscheidung jedoch von G and (not F)zu um(not G) or F , da oder in Chip impliziert sein kann.

Dieser resultierende wahre / falsche Wert wird dann in platziert a das niedrigste Bit der Ausgabe platziert. (Alle anderen Bits sind Null). Im TIO führe ich die Ausgabe über Hexdump aus, damit die Werte sichtbar sind.

Entsprechend würde man in C-ish etwa sagen:

out_byte = !(in_byte & 0x40) && (in_byte & 0x20)
Phlarx
quelle
1

Cubix, 16 Bytes

$-!u'HIa'@/1@O<

Netzform:

    $ -
    ! u
' H I a ' @ / 1
@ O < . . . . .
    . .
    . .

Versuch es selber

Sie sollten die dezimalen Bytewerte der Datei in einer getrennten Liste eingeben. Das Trennzeichen spielt keine Rolle, alles, was keine Ziffer oder ein Minuszeichen ist, reicht aus. Der Code kümmert sich wirklich nur um das erste Byte, so dass Sie den Rest der Datei weglassen können, wenn Sie möchten. Das Programm gibt 0für verlustfrei und 1für verlustbehaftet aus. Probieren Sie es hier aus ! Die Standardeingabe verwendet einen FLAC-Header.

Erläuterung

Das Schöne an Dateien ist, dass (fast) alle eine sogenannte Magie haben. Das sind die ersten Bytes der Datei. Gute Software überprüft nicht die Dateierweiterung, sondern die Dateizauber, um festzustellen, ob eine bestimmte Datei verarbeitet werden kann.

Dennis hat einen Weg gefunden, mit dieser Magie den Komprimierungstyp zu finden, aber die Tatsache, dass er das erste Byte verworfen hat, hat mich dazu veranlasst, eine Methode zu entwickeln, die das erste Byte und nicht das zweite Byte verwendet. In dieser Community geht es schließlich darum, Bytes zu sparen.

Hier ist eine Liste der ersten Bytes der verschiedenen Dateitypen. Ich habe sie in zwei Gruppen eingeteilt: verlustbehaftet und verlustfrei. Hier sind die Werte ihres ersten Bytes in Dezimal, Hexadezimal und Binär. Möglicherweise sehen Sie bereits ein Muster ...

Lossy:                  Lossless:
255:0xFF:0b11111111     102:0x66:0b01100110
 79:0x4F:0b01001111      84:0x54:0b01010100
 35:0x23:0b00100011      82:0x52:0b01010010
 11:0x0B:0b00001011      70:0x46:0b01000110
  0:0x00:0b00000000

Das Muster, das ich sah, war, dass das zweite Bit (von links nach rechts gezählt) in den "verlustfreien" Bytes immer an und das fünfte Bit immer aus war. Diese Kombination wird in keinem der verlustbehafteten Formate angezeigt. Um dies zu "extrahieren", würden wir einfach ein binäres UND (von 0b01001000 (=72)) machen und dann mit vergleichen 0b01000000 (=64). Wenn beide gleich sind, ist das Eingabeformat verlustfrei, andernfalls ist es verlustbehaftet.

Leider hat Cubix keinen solchen Vergleichsoperator, also habe ich Subtraktion verwendet (wenn das Ergebnis 64 ist, ergibt dies 0 und es ergibt 8, -56 oder -64, sonst. Ich werde später darauf zurückkommen.

Beginnen wir am Anfang des Programms. Das binäre UND geschieht mit dem aBefehl:

'HIa
'H   # Push 0b01001000 (72)
  I  # Push input
   a # Push input&72

Dann vergleichen wir mit 64 durch Subtraktion (beachten Sie, dass wir einen Spiegel treffen, der die IP auf die Oberseite [erste Zeile, zweites Zeichen, nach Süden zeigend] in der Mitte dieses Teils reflektiert).

'@-
'@  # Push 0b01000000 (64)
  - # Subtract from (input&72)
    # Yields 0 for lossy, non-zero otherwise

Nachdem die IP durch den umgedreht wurde u, verwenden wir einen Kontrollfluss, um a 1auf den Stapel zu schieben , wenn (und nur wenn) die Oberseite des Stapels nicht Null ist:

!$1
!   # if top = 0:
 $1 #   do nothing
    # else:
  1 #   push 1

Nachdem wir uns um den Würfel gewickelt haben, treffen wir die <Anweisung, die die IP nach Westen auf die vierte Zeile zeigt. Sie müssen nur noch ausgeben und beenden.

O@
O  # Output top of the stack as number
 @ # End program

Das Programm gibt also 0verlustfrei und 1verlustbehaftet aus.

Luke
quelle