Kayıplı mı, Kayıpsız mı?


18

Bir ses dosyası verildiğinde, dosyanın kayıplı bir formatta mı yoksa kayıpsız bir formatta mı kodlandığını belirleyin. Bu zorluğun amaçları doğrultusunda, yalnızca aşağıdaki biçimlerin sınıflandırılması gerekir:

kurallar

  • Giriş bir dosya adı biçiminde alınırsa, dosya adı hakkında herhangi bir varsayım yapılmamalıdır (örneğin, uzantının biçim için doğru olduğu veya hatta mevcut olduğu garanti edilmez).
  • Girdi dosyalarında ID3 veya APEv2 meta verileri bulunmayacak.
  • 0Ve 1, lossyve lossless, foove gibi iki benzersiz ve ayırt edilebilir çıktı kullanılabilir bar.

Test Durumları

Bu soruna yönelik test senaryoları, burada bulunan iki dizin içeren bir zip dosyasından oluşur : lossyve lossless. Her dizin, çeşitli biçimlerde kodlanmış 0,5 saniye 440 Hz sinüs dalgaları olan birkaç ses dosyası içerir. Tüm ses dosyalarının, A440.m4a(MPEG Katman 4 kapsayıcısındaki AAC ses) hariç, yukarıdaki biçimlerle eşleşen uzantıları vardır .


" Bir MPEG Katman 4 kapsayıcısındaki AAC ses " şu soruyu gündeme getirir: yanıtların başka hangi kap biçimlerini işlemesi gerekir?
Peter Taylor

@PeterTaylor FACMPEG aracılığıyla bir MPEG Katman 4 kapsayıcısına gömmeden AAC sesi sağlamanın bir yolunu bulamadığım için yalnızca AAC'ye özel bir söz verildi. Vorbis sesi bir Ogg kabına gömülüdür (Vorbis sesi normu gibi). Diğerleri bağımsız biçimlerdir.
Mego

TTA dosyanızdan emin misiniz? Spesifikasyona göre , TTA dosyaları sihirli sayı TTA1 veya TTA2 ile başlamalıdır. FFM2 (dosyanızın sihirli numarası) FFmpeg akışına karşılık geliyor. Linux dosyası TTA1 başlığını tanır, ancak FFM2 başlığını tanımaz.
Dennis

Ayrıca, AAC'nin her zaman bir MPEG Katman 4 başlığında olacağını varsayabilir miyiz? Değilse, ne olabilir varsayıyoruz?
Dennis

Dosyanın içeriğini girdi olarak alabilir miyiz veya kodumuz bunları almak zorunda mı?
Shaggy

Yanıtlar:


18

Jöle , 7 5 bayt

ƈƈeØA

Kayıplı biçimler 0 , kayıpsız biçimler 1 döndürür .

Çevrimiçi deneyin! (Gist'teki kalıcı bağlantılar)

Arka fon

Desteklememiz gereken biçimler aşağıdaki sihirli sayılara sahiptir, yani bu baytlarla başlarlar.

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

Girintili girdiler, test örneklerinde görünen önceki biçime yönelik kaplardır. ?bir değişken baytı belirtir. ."yazdırılamaz bayt" ı belirtir. Diğer tüm baytlar ISO 8859-1 karakterleri olarak görüntülenir.

Yalnızca ikinci bayta bakarak biçimi kolay bir şekilde belirleyebiliriz:

Kayıpsız biçimlerde ikinci bayt olarak büyük harf bulunurken, kayıplı biçimlerde yoktur.

Nasıl çalışır

ƈƈ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
Bu çok zekice bir çözüm.
Mego

10

C, 82 80 32 bayt

@Dennis'in cevabından esinlenerek , bu daha da azaltılabilir:

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

Dosya verilerini stdin'e aktarın. Kayıpsız için 0, kayıplı için sıfır değil.

Veya orijinal daha uzun kontrol:

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

Dosya verilerini stdin'e aktarın. Kayıpsız için sıfır olmayan (1) veya kayıplı için 0 döndürür.

Söyleyebileceğim kadarıyla, listelediğiniz tüm formatların ayrı sihirli sayıları var (AIFF / WAV hariç, ancak her ikisi de yine de kayıpsız), bu yüzden bu büyü numarasını bilinen kayıpsız bir değer için kontrol ediyor. *v&&Sadece boş bir byte (M4A) ile başlayan dosyalar eşleşen karşı korumaktır.

Spesifikasyon sayfalarında bulduğum değerleri ekledim ( fLaC= FLAC, RIFF= WAV / AIFF, TTA1= TTA) ve FORM= AIFF ve FFM2= TTA sağlanan örnek dosyalardan (sadece bunlar sarıcı formatları veya sonraki sürümler) tahmin edebilirim.


Veya daha kısa bir hile gibi bir alternatif:

Bash + dosya, 61 bayt

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

Dosya adını argüman olarak alır. Kayıpsız için 0, kayıplı için sıfır değil.

Tam olarak beklediğiniz şeyi yapar; filedosya türünün ne olduğunu sorar , sonra bilinen kalıpları kontrol eder. TTA eşleşmeleri : d( : data), AIFF / WAV eşleşmesi IFve FLAC eşleşmeleri FL. Kayıpsız sonuçların hiçbiri bunlardan hiçbiriyle eşleşmiyor ve dosya adları kaldırılırsa yine de çalıştığını test ettim.


Test yapmak:

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

Dosya uzantısı yanlışsa Bash çözümünüz de çalışıyor mu? "uzantının biçim için doğru olması garanti edilmez", bu nedenle bir dosyaya yanlış uzantı verebilmeniz ve yine de çalıştırabilmeniz gerekir.
mbomb007

@ mbomb007 Uzantıları karıştırarak test ettim ve hala onları iyi tanımlıyor. Ben filezaten uzantıları güvenmiyorum (jpeg için bir png yeniden adlandırma birçok kullanıcı şey dönüştürmek aynıdır!)
Dave

7

GS2 , 3 bayt

◄5ì

Kayıplı biçimler 0 , kayıpsız biçimler 1 döndürür .

Çevrimiçi deneyin! (Gist'teki kalıcı bağlantılar)

Arka fon

Desteklememiz gereken biçimler aşağıdaki sihirli sayılara sahiptir, yani bu baytlarla başlarlar.

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

Girintili girdiler, test örneklerinde görünen önceki biçime yönelik kaplardır. ?bir değişken baytı belirtir. ."yazdırılamaz bayt" ı belirtir. Diğer tüm baytlar ISO 8859-1 karakterleri olarak görüntülenir.

Yalnızca ikinci bayta bakarak biçimi kolay bir şekilde belirleyebiliriz:

Kayıpsız biçimlerde ikinci bayt olarak büyük harf bulunurken, kayıplı biçimlerde yoktur.

Nasıl çalışır

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

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

açıklama

Girdi olarak dosyanın içeriğini alır ve döner truedosya kayıpsız ise ya falseda bir olup olmadığını görmek için bu girişin ilk karakteri test ederek kayıplı ise f, F, Rveya T.


Dene

Bir dosyanın içeriğini textarea.

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


İkinci çaba, 81 63 bayt

Verilen bir URL'den dosyanın içeriğini aşırı doldurulmuş olduğu ortaya çıkarır.

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

İlk çaba, 146 116 89 bayt

Mime türleri uzantılara bağlı olduğundan ve görünüşe göre yanıt başlıkları ek girdi olarak nitelendirildiğinden geçersizdir.

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

web sunucuları genellikle MIME'yi, buradaki kurallara aykırı olan dosya uzantısına göre oluşturur. Uzantısız sunulan dosyalar üzerinde çalışıp çalışmadığını kontrol ettiniz mi? (eğer öyleyse, muhtemelen "dil" in bir parçası olarak kullandığınız sunucunun adını eklemeniz gerekir)
Dave

1
@Dave Emin değiller. MIME ve uzantı hiç birbirine bağlı değildir. Bir dosyanın uzantısını değiştirir ve yüklerseniz, MIME türü, uzantı değil dosyanın gerçek içeriğinin MIME olur. Yine de, URL olarak giriş almaya izin verilmiyor olabilir. Emin değilim.
mbomb007

@ mbomb007 Bunu neden söylediğinden emin değilim; mime türleri bir internet sistemi, bir dosya sistemi / dosya değil, ve farkında olduğum sunucular, yapılandırılmış bir arama kullanarak uzantıya göre belirleyecek (sunum başlıklarının hızı için; sunmadan önce her dosyayı incelemek istemiyorlar) o). Örneğin Apache AddType <mime> <extension>veya IIS'leri ele alalım <MimeMap>. Tabii ki belirli bir kurulum veya dosya barındırma aracı uygun bir denetim yapabilir ve bu sunucu seçiminin cevabın bir parçası olmasını hak eder (dosya türünü belirleyen sunucu olduğu için!)
Dave

1
.NET ile dosya doğrulaması yaptım ve MIME türü, yüklemeden önce uzantı değiştirilse bile içerikle eşleşti.
mbomb007

@ mbomb007 sonra kullandığınız .NET bileşeni, yükleme sırasında veya dosyaları sunarken dosya denetimi yapmış olmalıdır (performans için yükleme sırasında tahmin ediyorum, ama asla bilemezsiniz). Orijinal yorumuma geri dönersek, bu yanıt "JavaScript + .NET SeverLibraryXYZ" gibi bir şey haline gelir. Bir URL'den girdi almaya gelince, neden tereddüt ettiğinizi görebiliyorum, ancak kişisel olarak sunucu seçimi belirtildiği sürece geçerli olduğunu düşüneceğim. Belki üzerinde mevcut bir meta var, ama sonuçta Mego'ya bağlı.
Dave

1

Çip , 11 bayt

~Z~S
t'G~aF

Utanmazca Dennis 'Jelly cevap Chip.

Kayıpsız getiri 0x0, kayıplı getiri 0x1.

Çevrimiçi deneyin , bağlantılar gist (burada TIO stratejisi için Dennis'e teşekkürler)

Açıklamak!

~Z~S
t'

Bu kısım temizliktir: Silk baytı tkipler ve ikinciden sonra erminat yapar.

G~aF

Bu kararın eti. Her giriş baytına bitler tarafından erişilir HGFEDCBA. Eğer Gkümesidir ve Fbayt aralığında araçlarının, değil 0x40için 0x5f( 'büyük harf' ve eldeki görev için iyi, yeterli uzunlukta eşdeğerdir).

Ancak, bayt tasarrufu için, bu kararın invert gelen G and (not F)etmek (not G) or F, çünkü yoksa artık Chip örtük olabilir.

Bu nihai / doğru değeri daha sonra içine yerleştirilir a, bu da çıktının en düşük bitidir. (Diğer tüm bitler sıfır olacaktır). TIO'da, değerleri görünür olacak şekilde çıktıyı hexdump üzerinden çalıştırıyorum.

Eşdeğer olarak, C-ish'de biri şöyle söylenebilir:

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

1

Cubix, 16 bayt

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

Net form:

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

Kendin dene

Dosya ondalık bayt değerlerini ayrı bir listeye girmelisiniz. Ayırıcı önemli değildir, basamak veya eksi işareti olmayan herhangi bir şey yeterlidir. Kod gerçekten sadece ilk baytı önemser, böylece isterseniz dosyanın geri kalanını dışarıda bırakabilirsiniz. Program 0kayıpsız ve 1kayıplı için çıktı. Burada deneyin ! Varsayılan giriş bir FLAC üstbilgisi kullanır.

açıklama

Dosyalar hakkında güzel olan şey, (neredeyse) hepsinin sözde sihire sahip olmasıdır. Bunlar dosyanın ilk birkaç baytıdır. İyi bir yazılım dosya uzantısını kontrol etmez, bunun yerine belirli bir dosyayı işleyip işleyemeyeceğini görmek için dosya büyüsünü kontrol eder.

Dennis, sıkıştırma türünü bulmak için bu büyüyü kullanmanın bir yolunu buldu, ancak ilk baytı atması beni ikinci bayttan ziyade ilk baytı kullanan bir yöntem bulmaya çalışmak istedi. Sonuçta, bu topluluk tamamen bayt tasarrufu ile ilgilidir.

Farklı dosya türlerinin ilk baytlarının listesi. Onları iki gruba ayırdım: kayıplı ve kayıpsız. Ondalık, onaltılı ve ikili sayıdaki ilk bayt değerleri aşağıda verilmiştir. Zaten bir desen görebilirsiniz ...

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

Gördüğüm desen, ikinci bitin (soldan sağa sayılan) her zaman "kayıpsız" baytlarda açık olması ve beşinci bitin her zaman kapalı olmasıydı. Bu kombinasyon hiçbir kayıplı formatta görünmez. Bunu "ayıklamak" için, basitçe bir ikili AND (by 0b01001000 (=72)) yapar ve sonra karşılaştırırız 0b01000000 (=64). Her ikisi de eşitse, giriş biçimi kayıpsızdır, aksi takdirde kayıptır.

Ne yazık ki, Cubix'in böyle bir karşılaştırma operatörü yok, bu yüzden çıkarma kullandım (sonuç 64 ise, bu 0 verir ve aksi takdirde 8, -56 veya -64 ile sonuçlanır. Buna daha sonra geri döneceğim.

İlk olarak, programın başından başlayalım. İkili AND akomutu kullanılarak yapılır :

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

Daha sonra, çıkarma kullanarak 64 ile karşılaştırırız (bu kısmın ortasında IP'yi üst yüze [ilk satır, ikinci karakter, güneyi işaret eder) yansıtan bir aynaya çarptığımızı unutmayın).

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

IP, tarafından döndürüldükten sonra, yığının üst kısmı sıfır değilse (ve yalnızca) yığına uitmek için bir miktar kontrol akışı kullanırız 1:

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

Küpün etrafına sarıldıktan sonra <, IP'yi dördüncü satırda gösteren talimatı vurduk. Tek yapmanız gereken çıktı ve sonlandırmak.

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

Böylece, program 0kayıpsız ve 1kayıplı için çıktı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.