손실 또는 무손실?


18

오디오 파일이 제공되면 손실 형식으로 인코딩되는지 무손실 형식으로 인코딩했는지 확인하십시오. 이 문제를 해결하기 위해 다음 형식 만 분류하면됩니다.

규칙

  • 파일 이름 형식으로 입력 한 경우 파일 이름에 대한 가정은 없어야합니다 (예 : 확장자가 형식에 맞거나 존재하지 않을 수도 있음).
  • 입력 파일에 ID3 또는 APEv2 메타 데이터가 없습니다.
  • 01, lossylossless, foobar등의 두 가지 고유하고 구별 가능한 출력이 사용될 수 있습니다 .

테스트 사례

이 문제에 대한 테스트 케이스가있는 zip 파일로 구성되어 여기에 두 개의 디렉토리를 포함 lossy하고 lossless. 각 디렉토리에는 다양한 형식으로 인코딩 된 0.5 초 440Hz 사인파 인 여러 오디오 파일이 있습니다. 모든 오디오 파일의 확장자는 위의 형식과 일치 A440.m4a하지만 MPEG MPEG 4 컨테이너의 AAC 오디오는 예외입니다 .


" MPEG Layer 4 컨테이너의 AAC 오디오 "는 다음과 같은 질문을 제기합니다. 답변을 처리하기 위해 필요한 다른 컨테이너 형식은 무엇입니까?
피터 테일러

@PeterTaylor FACPEG를 통해 MPEG Layer 4 컨테이너에 AAC 오디오를 포함시키지 않으면 서 AAC 오디오를 제공 할 수 없었기 때문에 AAC만이 특별히 언급되었습니다. Vorbis 오디오는 Ogg 컨테이너에 내장되어 있습니다 (Vorbis 오디오의 표준과 동일). 다른 모든 형식은 독립형 형식입니다.
Mego

TTA 파일이 확실합니까? spec 에 따르면 TTA 파일은 매직 번호 TTA1 또는 TTA2로 시작해야합니다. FFM2 (파일의 마법 번호)가 FFmpeg 스트림에 해당하는 것으로 보입니다. Linux 파일 은 TTA1 헤더를 인식하지만 FFM2 헤더는 인식하지 않습니다.
Dennis

또한 AAC가 항상 MPEG Layer 4 헤더에 있다고 가정 할 수 있습니까? 그렇지 않다면 무엇 을 가정 할 수 있습니까?
Dennis

파일의 내용을 입력으로 취하거나 코드에서 검색해야합니까?
Shaggy

답변:


18

젤리 , 7 5 바이트

ƈƈeØA

손실 형식은 0을 반환 하고 무손실 형식은 1을 반환 합니다.

온라인으로 사용해보십시오! (Gist의 퍼머 링크)

배경

우리가 지원해야하는 형식은 다음과 같은 매직 넘버를가집니다. 즉,이 바이트로 시작합니다.

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

들여 쓰기 된 항목은 테스트 사례에 나타나는 이전 형식의 컨테이너입니다. ?변수 바이트를 나타냅니다. .인쇄 불가능한 바이트를 나타냅니다. 다른 모든 바이트는 ISO 8859-1 문자로 표시됩니다.

두 번째 바이트 만 살펴보면 형식을 쉽게 결정할 수 있습니다.

무손실 형식은 두 번째 바이트로 대문자를 사용하지만 손실 형식은 그렇지 않습니다.

작동 원리

ƈƈ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.

2
이것은 매우 영리한 솔루션입니다.
Mego

10

C, 82 80 32 바이트

@Dennis의 답변에서 영감을 얻은 결과 훨씬 더 줄어들 수 있습니다.

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

파일 데이터를 stdin으로 파이프하십시오. 손실이 없으면 0을, 손실이 있으면 0이 아닌 값을 반환합니다.

또는 원래 더 이상 확인하십시오.

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

파일 데이터를 stdin으로 파이프하십시오. 손실이없는 경우 0이 아닌 값을 반환하고 손실이없는 경우 0을 반환합니다.

내가 알 수 있듯이, 나열된 모든 형식에는 별도의 마법 번호가 있습니다 (AIFF / WAV는 제외하지만 둘 다 무손실입니다). 이는 해당 마법 번호에서 알려진 무손실 값을 확인합니다. 는 *v&&단지 널 바이트 (M4A)로 시작 일치하는 파일에 대한 보호하는 것입니다.

사양 시트에서 찾은 값 ( fLaC= FLAC, RIFF= WAV / AIFF, TTA1= TTA)을 포함 시켰 으며 FORM= AIFF 및 FFM2= TTA는 제공된 샘플 파일에서 가져온 것입니다 (래퍼 형식 또는 이후 버전 인 것만 추측 할 수 있음).


또는 짧은 느낌의 부정 행위 대안 :

배쉬 + 파일, 61 바이트

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

파일 이름을 인수로 사용합니다. 손실이 없으면 0을, 손실이 있으면 0이 아닌 값을 반환합니다.

정확히 당신이 기대하는 것을 수행합니다; file파일 유형이 무엇인지 묻고 알려진 패턴을 확인합니다. TTA 일치 : d( : data), AIFF / WAV 일치 IF및 FLAC 일치 FL. 무손실 결과는 이들 중 어느 것과도 일치하지 않으며 파일 이름을 제거해도 여전히 작동하는지 테스트했습니다.


테스트 :

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 */*

파일 확장자가 올바르지 않으면 Bash 솔루션도 작동합니까? "확장자가 형식에 맞는지 보장하지 않습니다."따라서 파일에 잘못된 확장자를 부여해도 여전히 작동합니다.
mbomb007

@ mbomb007 방금 확장 프로그램을 혼합하여 테스트했지만 여전히 잘 식별됩니다. file어쨌든 확장 프로그램을 신뢰하지 않는다고 생각 합니다 (png의 이름을 jpeg로 바꾸는 많은 사용자는 그것을 변환하는 것과 같습니다!)
Dave

7

GS2 , 3 바이트

◄5ì

손실 형식은 0을 반환 하고 무손실 형식은 1을 반환 합니다.

온라인으로 사용해보십시오! (Gist의 퍼머 링크)

배경

우리가 지원해야하는 형식은 다음과 같은 매직 넘버를가집니다. 즉,이 바이트로 시작합니다.

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

들여 쓰기 된 항목은 테스트 사례에 나타나는 이전 형식의 컨테이너입니다. ?변수 바이트를 나타냅니다. .인쇄 불가능한 바이트를 나타냅니다. 다른 모든 바이트는 ISO 8859-1 문자로 표시됩니다.

두 번째 바이트 만 살펴보면 형식을 쉽게 결정할 수 있습니다.

무손실 형식은 두 번째 바이트로 대문자를 사용하지만 손실 형식은 그렇지 않습니다.

작동 원리

     (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.

2

자바 스크립트 (ES6), 20 바이트

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

설명

입력으로 파일의 내용을 취하고 복귀 true파일이 무손실인지 또는 false그것이이 있는지 그 입력의 첫 문자를 테스트하여 손실 인 경우 f, F, R또는 T.


시도 해봐

파일 내용을에 붙여 넣습니다 textarea.

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


두 번째 노력, 81 63 바이트

제공된 URL에서 파일 내용을 가져옵니다.

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

먼저 노력, 146 (116) 89 바이트

MIME 유형은 확장에 연결되어 있고 응답 헤더는 추가 입력으로 간주되므로 유효하지 않습니다.

u=>fetch(u).then(r=>alert(/aiff|flac|tta|wave|wav$/.test(r.headers.get("Content-Type"))))

웹 서버는 일반적으로 파일 확장자를 기반으로 MIME을 생성하며 여기에서는 규칙에 위배됩니다. 확장명이없는 파일에서 작동하는지 확인 했습니까? (그렇다면 "언어"의 일부로 사용중인 서버의 이름을 포함시켜야합니다)
Dave

1
@Dave 그들이하지 않는 것이 확실합니다. MIME과 확장은 서로 의존하지 않습니다. 파일 확장자를 변경하여 업로드하면 MIME 유형은 확장자가 아니라 파일의 실제 내용에 대한 MIME입니다. 그러나 URL로 입력하는 것은 허용되지 않습니다. 잘 모르겠습니다.
mbomb007

@ mbomb007 왜 그런 말을하는지 모르겠습니다. MIME 유형은 파일 시스템 / 파일이 아닌 인터넷 일이며, 내가 알고있는 서버는 구성된 조회를 사용하여 확장을 기반으로 확장을 기반으로 결정합니다 (헤더 제공 속도; 제공하기 전에 모든 파일을 검사하고 싶지는 않습니다. 그것). Apache AddType <mime> <extension>또는 IIS 를 예로 들어 보겠습니다 <MimeMap>. 물론 특정 설정 또는 파일 호스팅 도구는 적절한 검사를 수행 할 수 있으며 서버 선택이 답의 일부가되어야합니다 (파일 유형을 결정하는 서버이므로)!
Dave

1
.NET을 사용하여 파일 유효성 검사를 수행했으며 업로드 전에 확장명이 변경된 경우에도 MIME 유형이 내용과 일치했습니다.
mbomb007

@ mbomb007 그런 다음 사용하는 .NET 구성 요소가 업로드 중 또는 파일을 제공 할 때 파일 검사를 수행해야합니다 (업로드 중에는 성능을 위해 추측하지만 결코 알 수는 없습니다). 따라서 원래 의견으로 돌아가서 "JavaScript + .NET SeverLibraryXYZ"와 같은 답변을 만들었습니다. URL에서 입력하는 것에 대해 왜 주저하는지 알 수 있지만 개인적으로 서버 선택이 언급되는 한 개인적으로 유효하다고 생각합니다. 아마도 기존 메타가있을 수도 있지만 궁극적으로 Mego에 달려 있습니다.
Dave

1

, 11 바이트

~Z~S
t'G~aF

칩에서 Dennis의 Jelly 답변을 수치스럽게 복제했습니다.

무손실 수익률 0x0, 무손실 수익률 0x1.

온라인으로 사용해보십시오 . 요점에 대한 링크 (여기에서 TIO 전략에 대해 Dennis에게 감사드립니다)

설명!

~Z~S
t'

이 부분은 하우스 키핑입니다. S첫 번째 바이트를 키핑 t하고 두 번째 바이트 후에 종료합니다.

G~aF

이것이 결정의 고기입니다. 각 입력 바이트는 비트에 의해 액세스됩니다 HGFEDCBA. 경우에 G설정되고, F바이트의 범위 내에 있다는 의미없는 0x400x5f( '대문자'및 수중 작업을위한 충분한 대략 동일하다).

그러나 바이트 절약을 G and (not F)위해 (not G) or F칩에서 암시 적 또는가 암시 할 수 있기 때문에이 결정을에서 로 바꿉니다.

이 결과 true / false 값이 a출력의 가장 낮은 비트 인에 배치됩니다 . 다른 모든 비트는 0이됩니다. TIO에서는 hexdump를 통해 출력을 실행하여 값을 볼 수 있습니다.

마찬가지로 C-ish에서는 다음과 같이 말할 수 있습니다.

out_byte = !(in_byte & 0x40) && (in_byte & 0x20)

1

Cubix, 16 바이트

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

순수한 형태 :

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

직접 해보십시오

파일 10 진수 바이트 값을 분리 된 목록으로 입력해야합니다. 구분 기호는 중요하지 않습니다. 숫자 나 빼기 기호가 아닌 것은 충분합니다. 코드는 실제로 첫 번째 바이트에만 관심이 있으므로 원하는 경우 파일의 나머지 부분을 생략 할 수 있습니다. 이 프로그램 0은 무손실 및 1손실로 출력 됩니다 . 여기에서 보십시오 ! 기본 입력은 FLAC 헤더를 사용합니다.

설명

파일에 대한 좋은 점은 (거의) 모든 파일에 소위 마법이 있다는 것입니다. 그것들은 파일의 처음 몇 바이트입니다. 좋은 소프트웨어는 파일 확장자를 검사하지 않고 특정 파일을 처리 할 수 ​​있는지 확인하기 위해 파일 마법을 검사합니다.

Dennis는이 마술을 사용하여 압축 유형을 찾는 방법을 찾았지만 첫 번째 바이트를 버렸다는 사실 때문에 두 번째 바이트가 아닌 첫 번째 바이트를 사용하는 방법을 생각해 냈습니다. 결국이 커뮤니티는 바이트 절약에 관한 것입니다.

다른 파일 형식의 첫 번째 바이트 목록은 다음과 같습니다. 나는 그것들을 손실과 무손실의 두 그룹으로 주문했다. 다음은 첫 번째 바이트 값을 10 진수, 16 진수 및 2 진수로 나타낸 것입니다. 당신은 이미 패턴을 볼 수 있습니다 ...

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

내가 본 패턴은 두 번째 비트 (왼쪽에서 오른쪽으로 계산)가 항상 "손실없는"바이트에 있고 다섯 번째 비트는 항상 꺼져 있다는 것입니다. 이 조합은 손실 형식으로 나타나지 않습니다. 이것을 "추출"하기 위해 간단히 이진 AND를 수행 0b01001000 (=72)하고 다음과 비교합니다 0b01000000 (=64). 둘 다 동일하면 입력 형식이 손실이없고, 그렇지 않으면 손실입니다.

안타깝게도 Cubix에는 그러한 비교 연산자가 없으므로 뺄셈을 사용했습니다 (결과가 64이면 0이되고 그렇지 않으면 8, -56 또는 -64가됩니다. 나중에 다시 설명하겠습니다).

먼저 프로그램 시작 부분부터 시작하겠습니다. 이진 AND는 다음 a명령을 사용하여 수행됩니다.

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

그런 다음 빼기를 사용하여 64와 비교합니다 (이 부분의 중간에서 IP를 맨 위 얼굴 (첫 번째 줄, 두 번째 문자, 남쪽을 가리킴)에 반영하는 미러를 쳤습니다).

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

에 의해 IP가 바뀌면 스택의 상단이 0이 아닌 경우에만 u제어 흐름을 사용 1하여 스택에 a 를 푸시 합니다.

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

입방체를 감싼 후, 우리 <는 네 번째 줄에서 IP 서쪽을 가리키는 지시를 받았습니다. 남은 일은 출력과 종료입니다.

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

따라서 프로그램 0은 무손실 및 1손실로 출력 됩니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.