Втрачений чи без втрат?


18

Давши аудіофайл, визначте, чи він закодований у форматі втрат чи у форматі без втрат. Для цілей цього виклику потрібно класифікувати лише такі формати:

Правила

  • Якщо введення приймається у формі імені файлу, не слід робити припущень щодо імені файлу (наприклад, розширення не гарантується, що воно є правильним для формату або навіть наявного).
  • У вхідних файлах не буде присутній метаданих ID3 або APEv2.
  • Будь-які дві унікальні і помітні виходи можуть бути використані, наприклад, 0і 1, lossyі lossless, fooі barт.д.

Випробування

Тестові приклади для цього виклику складаються з zip-файлів, розміщених тут, який містить два каталоги: lossyі lossless. Кожен каталог містить декілька аудіофайлів, які є синусоїдами хвилі 440 Гц, що кодуються в різних форматах. Усі аудіофайли мають розширення, що відповідають форматам, наведеним вище, за винятком A440.m4a(який є аудіо AAC у контейнері MPEG рівня 4).


" Аудіо AAC в контейнері MPEG рівня 4 " викликає питання: з якими іншими форматами контейнерів потрібно відповідати?
Пітер Тейлор

@PeterTaylor Тільки AAC було відзначено особливою згадкою, оскільки я не зміг знайти спосіб надати аудіо AAC, не вставивши його в контейнер MPEG рівня 4 через FFMPEG. Аудіо Vorbis вбудовується в контейнер Ogg (як це норма для аудіо Vorbis). Усі інші - це окремі формати.
Мего

Ви впевнені у файлі TTA? Відповідно до специфікації , файли TTA повинні починатися з магічного числа TTA1 або TTA2. Здається, FFM2 (магічне число вашого файлу) відповідає потоку FFmpeg. Файл Linux розпізнає заголовок TTA1, але не FFM2.
Денніс

Також чи можна вважати, що AAC завжди буде знаходитись у заголовку рівня MPEG 4? Якщо немає, то може ми припускаємо?
Денніс

Чи можемо ми взяти вміст файлу як вхідний текст або чи повинен наш код їх отримати?
Кудлатий

Відповіді:


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
Це дуже розумне рішення.
Мего

10

C, 82 80 32 байти

Натхненний відповіддю @Dennis , це можна значно зменшити:

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

Передача даних файлу в stdin. Повертає 0 для втрат без втрат, або нульове значення для втрати.

Або оригінальний довший чек:

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

Передача даних файлу в stdin. Повертає нульове значення (1) для без втрат або 0 для втрат.

Як я можу сказати, усі перелічені вами формати мають окремі магічні цифри (крім 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 для втрат без втрат, або нульове значення для втрати.

Робить саме те, що ви очікували; запитує, fileщо таке тип файлу, потім перевіряє відомі шаблони. TTA match : d( : data), AIFF / WAV match IFта FLAC match 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ì

Формати втрат повертають 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

JavaScript (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 на основі розширення файлу, що суперечить правилам тут. Ви перевірили, чи працює він на файлах, що подаються без розширення? (якщо так, то, ймовірно, ви повинні вказати ім’я сервера, який ви використовуєте як частину "мови")
Дейв,

1
@Dave Досить впевнені, що цього не роблять. MIME і розширення взагалі не залежать один від одного. Якщо змінити розширення файлу і завантажити його, тип MIME є MIME фактичного вмісту файла, а не розширення. Однак, можливо, забороняється приймати введення даних як URL-адресу. Я не впевнений.
mbomb007

@ mbomb007 Я не впевнений, чому ти це кажеш; типи mime - це Інтернет-річ, а не файлова система / файл, і сервери, про які я знаю, визначатимуть це на основі розширення за допомогою налаштованого пошуку (для швидкості обслуговування заголовків; вони не хочуть перевіряти кожен файл перед подачею це). Візьмемо для прикладу Apache AddType <mime> <extension>, або IIS <MimeMap>. Звичайно, певний інструмент налаштування або розміщення файлів може зробити належну перевірку, і це заслуговує на те, щоб вибір сервера був частиною відповіді (адже саме сервер визначає тип файлу!)
Дейв,

1
Я провів перевірку файлів за допомогою .NET, і тип MIME відповідав вмісту, навіть коли розширення було змінено перед завантаженням.
mbomb007

@ mbomb007 тоді будь-який компонент .NET, який ви використовували, повинен був здійснити перевірку файлів або під час завантаження, або під час обслуговування файлів (я б припустив під час завантаження для продуктивності, але ви ніколи не знаєте). Повертаючись до мого оригінального коментаря, це зробить цю відповідь чимось на кшталт "JavaScript + .NET SeverLibraryXYZ". Що стосується отримання даних з URL-адреси, я бачу, чому ви вагаєтесь, але особисто я вважаю це дійсним до тих пір, поки буде вказано вибір сервера. Можливо, в ньому є мета, але, зрештою, це залежить від Mego.
Дейв

1

Чіп , 11 байт

~Z~S
t'G~aF

Безсоромно тиражував відповідь Дженніса в чіпі.

Беззбитковість 0x0, збитковість 0x1.

Спробуйте в Інтернеті , посилання в суті (дякую Деннісу за стратегію TIO тут)

Поясніть!

~Z~S
t'

Ця частина веде господарство: вона Sкидає перший байт, а tермінує після другого.

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і без втрат, і 1для втрат. Спробуйте тут ! За замовчуванням використовується заголовок 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

Я бачив, що другий біт (рахується зліва направо) завжди був на байтах без втрат, а п'ятий біт завжди був відключений. Ця комбінація не відображається в жодному із форматів втрат. Щоб "витягти" це, ми просто зробимо двійковий І (від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-адресою uми використовуємо деякий потік управління, щоб натиснути a 1на стек, якщо (і лише якщо) верхня частина стека не дорівнює нулю:

!$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для втрат.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.