ความสูญเสียหรือความสูญเสีย?


18

ให้ไฟล์เสียงตรวจสอบว่ามีการเข้ารหัสในรูปแบบ lossy หรือรูปแบบ lossless สำหรับจุดประสงค์ของการท้าทายนี้จะต้องจัดประเภทเฉพาะรูปแบบต่อไปนี้:

กฎระเบียบ

  • หากนำเข้ามาในรูปแบบของชื่อไฟล์ไม่ควรมีข้อสันนิษฐานเกี่ยวกับชื่อไฟล์ (เช่นนามสกุลไม่รับประกันว่าถูกต้องสำหรับรูปแบบหรือแม้กระทั่งปัจจุบัน)
  • จะไม่มีข้อมูลเมตา ID3 หรือ APEv2 ในไฟล์อินพุต
  • สองเอาท์พุทที่เป็นเอกลักษณ์และความแตกต่างอาจจะใช้เช่น0และ1, lossyและlossless, fooและbarอื่น ๆ

กรณีทดสอบ

กรณีทดสอบสำหรับความท้าทายนี้ประกอบด้วยไฟล์ซิปอยู่ที่นี่ซึ่งมีสองไดเรกทอรี: และlossy losslessแต่ละไดเรกทอรีมีไฟล์เสียงหลายไฟล์ที่เป็นคลื่นไซน์ 440 Hz ทั้งหมด 0.5 วินาทีซึ่งเข้ารหัสในรูปแบบต่างๆ ไฟล์เสียงทั้งหมดมีส่วนขยายที่ตรงกับรูปแบบด้านบนยกเว้นA440.m4a(ซึ่งคือเสียง AAC ในคอนเทนเนอร์ MPEG Layer 4)


" เสียง AAC ในคอนเทนเนอร์ MPEG Layer 4 " ทำให้เกิดคำถาม: คำตอบรูปแบบคอนเทนเนอร์อื่นใดที่ต้องจัดการ
Peter Taylor

@PeterTaylor มีเพียง AAC เท่านั้นที่ได้รับการกล่าวถึงเป็นพิเศษเพราะฉันไม่สามารถหาวิธีให้เสียง AAC ได้โดยไม่ต้องฝังไว้ในคอนเทนเนอร์ MPEG Layer 4 ผ่าน FFMPEG เสียง Vorbis ฝังอยู่ในคอนเทนเนอร์ Ogg (ตามปกติสำหรับเสียง Vorbis) อื่น ๆ ทั้งหมดเป็นรูปแบบสแตนด์อโลน
Mego

คุณแน่ใจเกี่ยวกับไฟล์ TTA หรือไม่ ตามข้อมูลจำเพาะไฟล์ TTA ควรเริ่มต้นด้วยหมายเลขมายากล TTA1 หรือ TTA2 FFM2 (หมายเลขเวทย์มนตร์ของไฟล์ของคุณ) ปรากฏขึ้นเพื่อให้สอดคล้องกับสตรีม FFmpeg ไฟล์ Linux รู้จักส่วนหัว TTA1 แต่ไม่ใช่ส่วนหัว FFM2
Dennis

นอกจากนี้เราสามารถสมมติได้ว่า AAC จะอยู่ในส่วนหัวของ MPEG Layer 4 หรือไม่? ถ้าไม่ได้สิ่งที่สามารถเราคิด?
เดนนิส

เราสามารถนำเนื้อหาของไฟล์มาเป็นข้อมูลนำเข้าหรือไม่หรือรหัสของเราจะต้องทำการดึงออกมาได้หรือไม่?
Shaggy

คำตอบ:


18

เยลลี่ , 7 5 ไบต์

ƈƈeØA

รูปแบบ Lossy กลับ0รูปแบบ lossless กลับ1

ลองออนไลน์! (Permalinks ในส่วนสำคัญ)

พื้นหลัง

รูปแบบที่เราต้องสนับสนุนมีหมายเลขเวทย์มนตร์ต่อไปนี้กล่าวคือเริ่มต้นด้วยไบต์เหล่านี้

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

โดยการดูที่ไบต์ที่สองเท่านั้นเราสามารถกำหนดรูปแบบได้อย่างง่ายดาย:

รูปแบบ Lossless มีตัวอักษรตัวพิมพ์ใหญ่เป็นไบต์ที่สองในขณะที่รูปแบบ lossy ไม่มี

มันทำงานอย่างไร

ƈƈ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 สำหรับ lossless หรือไม่ใช่ศูนย์สำหรับ lossy

หรือตรวจสอบต้นฉบับอีกต่อไป:

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

ไพพ์ข้อมูลไฟล์ไปยัง stdin ส่งคืนค่าที่ไม่ใช่ศูนย์ (1) สำหรับ lossless หรือ 0 สำหรับ lossy

จากสิ่งที่ฉันสามารถบอกได้ว่ารูปแบบทั้งหมดที่คุณระบุไว้มีหมายเลขเวทย์มนตร์แยกต่างหาก (ยกเว้น AIFF / WAV แต่เป็นแบบที่ไม่มีการสูญเสีย) ดังนั้นนี่จะตรวจสอบหมายเลขมายากลนั้นเพื่อหาค่าการสูญเสียที่ทราบ *v&&เป็นเพียงเพื่อป้องกันไฟล์ที่ตรงกันซึ่งเริ่มต้นด้วยไบต์โมฆะ (M4A)

ฉันได้รวมค่าที่พบในแผ่นข้อมูลจำเพาะ ( fLaC= FLAC, RIFF= WAV / AIFF, TTA1= TTA) และFORM= AIFF และFFM2= TTA มาจากไฟล์ตัวอย่างที่มีให้


หรือทางเลือกที่ให้ความรู้สึกเหมือนโกงสั้น

ไฟล์ Bash + 61 ไบต์

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

ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์ ส่งคืนค่า 0 สำหรับ lossless หรือไม่ใช่ศูนย์สำหรับ lossy

ทำสิ่งที่คุณคาดหวัง ถามfileว่าชนิดไฟล์คืออะไรจากนั้นตรวจสอบรูปแบบที่รู้จัก การแข่งขันของ บริษัท ฯ: 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 ก็เหมือนกับการแปลงมัน!)
เดฟ

7

GS2 , 3 ไบต์

◄5ì

รูปแบบ Lossy กลับ0รูปแบบ lossless กลับ1

ลองออนไลน์! (Permalinks ในส่วนสำคัญ)

พื้นหลัง

รูปแบบที่เราต้องสนับสนุนมีหมายเลขเวทย์มนตร์ต่อไปนี้กล่าวคือเริ่มต้นด้วยไบต์เหล่านี้

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

โดยการดูที่ไบต์ที่สองเท่านั้นเราสามารถกำหนดรูปแบบได้อย่างง่ายดาย:

รูปแบบ Lossless มีตัวอักษรตัวพิมพ์ใหญ่เป็นไบต์ที่สองในขณะที่รูปแบบ lossy ไม่มี

มันทำงานอย่างไร

     (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

JavaScript (ES6), 20 ไบต์

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

คำอธิบาย

นำเนื้อหาของไฟล์ที่เป็น input และผลตอบแทนtrueถ้าไฟล์เป็น lossless หรือfalseถ้ามันเป็นความสูญเสียโดยการทดสอบตัวอักษรตัวแรกของการป้อนข้อมูลที่เพื่อดูว่ามันเป็นf, F, หรือRT


ลองมัน

textareaวางเนื้อหาของไฟล์ลงใน

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


ความพยายามครั้งที่สอง, 81 63 ไบต์

ดึงเนื้อหาของไฟล์จาก URL ที่ให้ซึ่งกลายเป็น overkill

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 ตามนามสกุลไฟล์ซึ่งผิดกฎที่นี่ คุณได้ตรวจสอบว่ามันทำงานกับไฟล์ที่ให้บริการโดยไม่มีนามสกุลหรือไม่? (ถ้าเป็นเช่นนั้นคุณควรรวมชื่อของเซิร์ฟเวอร์ที่คุณใช้เป็นส่วนหนึ่งของ "ภาษา")
เดฟ

1
@Dave ค่อนข้างแน่ใจว่าพวกเขาไม่ได้ MIME และนามสกุลไม่ได้ขึ้นอยู่กับแต่ละอื่น ๆ หากคุณเปลี่ยนนามสกุลไฟล์และอัปโหลดประเภท MIME คือ MIME ของเนื้อหาจริงของไฟล์ไม่ใช่นามสกุล อย่างไรก็ตามการรับอินพุตเป็น URL อาจไม่ได้รับอนุญาต ฉันไม่แน่ใจ.
mbomb007

@ mbomb007 ฉันไม่แน่ใจว่าทำไมคุณพูดอย่างนั้น; ประเภท mime เป็นสิ่งที่อินเทอร์เน็ตไม่ใช่สิ่งที่ระบบไฟล์ / ไฟล์และเซิร์ฟเวอร์ที่ฉันรู้จะกำหนดตามส่วนขยายโดยใช้การค้นหาที่กำหนดค่า (สำหรับความเร็วในการให้บริการส่วนหัวพวกเขาไม่ต้องการตรวจสอบทุกไฟล์ก่อนแสดง มัน). ใช้ตัวอย่างของ Apache AddType <mime> <extension>หรือ <MimeMap>IIS ของหลักสูตรการติดตั้งที่เฉพาะเจาะจงหรือไฟล์โฮสติ้งเครื่องมือที่สามารถทำการตรวจสอบที่เหมาะสมและที่จะทำบุญการเลือกเซิร์ฟเวอร์จะเป็นส่วนหนึ่งของคำตอบ (เนื่องจากเป็นเซิร์ฟเวอร์ที่กำหนดประเภทไฟล์!)
เดฟ

1
ฉันทำการตรวจสอบความถูกต้องของไฟล์ด้วย. NET และประเภท MIME นั้นตรงกับเนื้อหาแม้ว่าจะมีการเปลี่ยนแปลงส่วนขยายก่อนที่จะอัปโหลด
mbomb007

@ mbomb007 ส่วนใดที่. NET ที่คุณใช้ต้องทำการตรวจสอบไฟล์ระหว่างการอัพโหลดหรือเมื่อให้บริการไฟล์ (ฉันเดาระหว่างการอัปโหลดเพื่อประสิทธิภาพ แต่คุณไม่เคยรู้) ดังนั้นกลับไปที่ความคิดเห็นเดิมของฉันซึ่งจะทำให้คำตอบนี้เป็น "JavaScript + .NET SeverLibraryXYZ" สำหรับการรับข้อมูลจาก URL ฉันสามารถดูได้ว่าทำไมคุณถึงลังเล แต่โดยส่วนตัวฉันคิดว่ามันใช้ได้ตราบเท่าที่ตัวเลือกของเซิร์ฟเวอร์ถูกกล่าวถึง อาจจะมีเมตาดาต้าอยู่ แต่ท้ายที่สุดมันก็ขึ้นอยู่กับเมก้า
เดฟ

1

ชิป 11 ไบต์

~Z~S
t'G~aF

จำลองคำตอบของ Dennis 'Jelly ในชิป

ผลตอบแทน Lossless ผลตอบแทนที่สูญเสีย0x00x1

ลองออนไลน์ลิงก์ในส่วนสำคัญ (ขอบคุณ Dennis สำหรับกลยุทธ์ TIO ที่นี่)

อธิบาย!

~Z~S
t'

ส่วนนี้คือการทำความสะอาด: มันSบีบข้อมูลไบต์แรกและterminates หลังจากวินาที

G~aF

นี่คือเนื้อของการตัดสินใจ HGFEDCBAแต่ละไบต์การป้อนข้อมูลการเข้าถึงโดยบิต ถ้าGเป็นชุดและFไม่ได้หมายความว่าไบต์อยู่ในช่วง0x40ที่จะ0x5f(ซึ่งเป็นประมาณเทียบเท่ากับ 'พิมพ์ใหญ่' และดีพอสำหรับงานในมือ)

อย่างไรก็ตามสำหรับการประหยัดแบบไบต์ฉันกลับการตัดสินใจนี้จากG and (not F)เป็น(not G) or Fเนื่องจากหรืออาจเป็นนัยในชิป

ผลลัพธ์จริง / เท็จค่านี้จะถูกวางไว้aซึ่งเป็นบิตที่ต่ำที่สุดของการส่งออก (บิตอื่น ๆ ทั้งหมดจะเป็นศูนย์) ใน 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 < . . . . .
    . .
    . .

ลองด้วยตัวคุณเอง

คุณควรป้อนค่าไบต์ไฟล์ทศนิยมในรายการแยกกัน ตัวคั่นไม่สำคัญสิ่งใดก็ตามที่ไม่ใช่ตัวเลขหรือเครื่องหมายลบเพียงพอ รหัสนี้ให้ความสำคัญกับไบต์แรกเท่านั้นดังนั้นคุณสามารถปล่อยส่วนที่เหลือของไฟล์ได้หากคุณต้องการ โปรแกรมแสดงผล0เป็น lossless และ1lossy ลองที่นี่ ! อินพุตเริ่มต้นใช้ส่วนหัว FLAC

คำอธิบาย

สิ่งที่ดีเกี่ยวกับไฟล์คือ (เกือบ) พวกเขาทั้งหมดมีเวทมนตร์ที่เรียกว่า นี่เป็นจำนวนไบต์แรกของไฟล์ ซอฟต์แวร์ที่ดีไม่ได้ตรวจสอบนามสกุลไฟล์ แต่ควรใช้ความมหัศจรรย์ของไฟล์เพื่อดูว่าสามารถจัดการไฟล์บางไฟล์ได้หรือไม่

เดนนิสพบวิธีที่จะใช้เวทย์มนตร์นี้เพื่อค้นหาประเภทการบีบอัด แต่ความจริงที่ว่าเขาละทิ้งไบต์แรกทำให้ฉันต้องการลองใช้วิธีที่ใช้ไบต์แรกแทนที่จะเป็นวินาที ท้ายที่สุดชุมชนนี้เป็นเรื่องเกี่ยวกับการบันทึกไบต์

นี่คือรายการไบต์แรกของไฟล์ประเภทต่างๆ ฉันสั่งให้พวกเขาออกเป็นสองกลุ่ม: การสูญเสียและการสูญเสีย นี่คือค่าของไบต์แรกของพวกเขาในทศนิยมฐานสิบหกและไบนารี คุณอาจเห็นรูปแบบแล้ว ...

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

รูปแบบที่ฉันเห็นคือบิตที่สอง (นับจากซ้ายไปขวา) เปิดอยู่บนไบต์ "lossless" เสมอและบิตที่ห้าถูกปิดเสมอ ชุดนี้ไม่ปรากฏในรูปแบบที่สูญเสียใด ๆ ถึง "สารสกัดจาก" นี้เราก็จะทำไบนารีและ (โดย0b01001000 (=72)) 0b01000000 (=64)แล้วเปรียบเทียบกับ หากทั้งสองเท่ากันรูปแบบการป้อนข้อมูลจะไม่มีความสูญเสีย

น่าเสียดายที่ Cubix ไม่มีตัวดำเนินการเปรียบเทียบดังนั้นฉันจึงใช้การลบ (ถ้าผลลัพธ์คือ 64 นี่ให้ผลเป็น 0 และมันให้ผลลัพธ์เป็น 8, -56 หรือ -64 เป็นอย่างอื่นฉันจะกลับไปหาสิ่งนี้ในภายหลัง

ก่อนอื่นเรามาเริ่มที่จุดเริ่มต้นของโปรแกรมกันก่อน ไบนารีและเสร็จสิ้นโดยใช้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 หมุนไปรอบ ๆuแล้วเราใช้การควบคุมการไหลเพื่อดัน a 1ไปยัง stack หาก (และเฉพาะในกรณี) ด้านบนสุดของ stack ไม่เป็นศูนย์:

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

หลังจากที่เราล้อมรอบลูกบาศก์เรากด<คำแนะนำซึ่งชี้ IP ตะวันตกบนบรรทัดที่สี่ สิ่งที่เหลืออยู่ที่ต้องทำคือเอาท์พุทและยุติ

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

ดังนั้นโปรแกรมจะแสดงผล0เป็น lossless และ1สำหรับ lossy

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.