Μέθοδοι συμπίεσης/αποθήκευσης δεδομένων μέσων σε μορφές WAVE και JPEG, μέρος 1

Γειά σου! Η πρώτη μου σειρά άρθρων θα επικεντρωθεί σε μεθόδους συμπίεσης και αποθήκευσης εικόνας/ήχου όπως JPEG (εικόνες) και WAVE (ήχος), και θα περιλαμβάνει επίσης παραδείγματα προγραμμάτων που χρησιμοποιούν αυτές τις μορφές (.jpg, .wav) στην πράξη. Σε αυτό το μέρος θα δούμε συγκεκριμένα το WAVE.

Ιστορία

Το WAVE (Waveform Audio File Format) είναι μια μορφή αρχείου κοντέινερ για την αποθήκευση εγγραφών ροής ήχου. Αυτό το δοχείο χρησιμοποιείται συνήθως για την αποθήκευση ασυμπίεστου ήχου διαμόρφωσης κωδικού παλμού. (Λήψη από τη Wikipedia)

Εφευρέθηκε και δημοσιεύτηκε το 1991 μαζί με το RIFF από τη Microsoft και την IBM (Κορυφαίες εταιρείες πληροφορικής εκείνης της εποχής).

Δομή αρχείου

Το αρχείο έχει κεφαλίδα, τα ίδια τα δεδομένα, αλλά όχι υποσέλιδο. Η κεφαλίδα ζυγίζει 44 byte συνολικά.
Η κεφαλίδα περιέχει ρυθμίσεις για τον αριθμό των bit στο δείγμα, τη συχνότητα δειγματοληψίας, το βάθος ήχου κ.λπ. που απαιτούνται για την κάρτα ήχου. (Όλες οι αριθμητικές τιμές στον πίνακα πρέπει να γράφονται με σειρά Little-Endian)

Όνομα μπλοκ
Μέγεθος μπλοκ (Β)
Περιγραφή/Σκοπός
Τιμή (για κάποιους είναι σταθερή)

chunkId
4
Ορισμός αρχείου ως κοντέινερ πολυμέσων
0x52494646 σε Big-Endian ("RIFF")

chunkSize
4
Μέγεθος ολόκληρου του αρχείου χωρίς chunkId και chunkSize
FILE_SIZE — 8

μορφή
4
Ορισμός τύπου από το RIFF
0x57415645 σε Big-Endian ("WAVE")

subchunk1Id
4
Για να καταλάβετε περισσότερο χώρο, συνεχίστε τη διαμόρφωση
0x666d7420 σε Big-Endian ("fmt")

subchunk1Μέγεθος
4
Υπόλοιπη κεφαλίδα (σε byte)
16 από προεπιλογή (για θήκη χωρίς συμπίεση ροής ήχου)

μορφή ήχου
2
Μορφή ήχου (εξαρτάται από τη μέθοδο συμπίεσης και τη δομή των δεδομένων ήχου)
1 (για PCM, που είναι αυτό που εξετάζουμε)

numChannels
2
Αριθμός καναλιών
1/2, θα πάρουμε 1 κανάλι (3/4/5/6/7… — συγκεκριμένο κομμάτι ήχου, για παράδειγμα 4 για quad ήχο κ.λπ.)

ρυθμός δειγματοληψίας
4
Συχνότητα δειγματοληψίας ήχου (σε Hertz)
Όσο υψηλότερη είναι η τιμή, τόσο καλύτερη θα είναι η ποιότητα του ήχου, αλλά όσο περισσότερη μνήμη θα απαιτείται για τη δημιουργία ενός κομματιού ήχου του ίδιου μήκους, η συνιστώμενη τιμή είναι 48000 (η πιο αποδεκτή ποιότητα ήχου)

byteRate
4
Αριθμός byte ανά 1 δευτερόλεπτο
ρυθμός δειγματοληψίας numChannels bitsPerSample (περισσότερα)

μπλοκΕυθυγράμμιση
2
Αριθμός byte για 1 δείγμα
numChannels * bitsPerSample: 8

bitsPerSample
2
Αριθμός bit ανά δείγμα (βάθος)
Οποιοσδήποτε αριθμός πολλαπλάσιο του 8. Όσο περισσότερο, τόσο καλύτερος και βαρύτερος θα είναι ο ήχος, τα 32 bit δεν έχουν καμία διαφορά για ένα άτομο

subchunk2Id
4
Σημάδι μέτρησης έναρξης δεδομένων (καθώς ενδέχεται να υπάρχουν άλλα στοιχεία κεφαλίδας ανάλογα με το audioFormat)
0x64617461 σε Big-Endian("δεδομένα")

subchunk2Μέγεθος
4
Μέγεθος περιοχής δεδομένων
μέγεθος δεδομένων σε int

ημερομηνία
byteRate * διάρκεια ήχου
Ηχητικά δεδομένα
?

Παράδειγμα με το WAVE

Ο προηγούμενος πίνακας μπορεί εύκολα να μεταφραστεί σε δομή C, αλλά η γλώσσα της επιλογής μας σήμερα είναι η Python. Το πιο εύκολο πράγμα που μπορείτε να κάνετε χρησιμοποιώντας το "κύμα" είναι να δημιουργήσετε μια γεννήτρια θορύβου. Για αυτήν την εργασία δεν χρειαζόμαστε υψηλό byteRate και συμπίεση.
Αρχικά, ας εισάγουμε τις απαραίτητες ενότητες:

# WAV.py

from struct import pack  # перевод py-объектов в базовые типы из C
from os import urandom  # функция для чтения /dev/urandom, для windows:
# from random import randint
# urandom = lambda sz: bytes([randint(0, 255) for _ in range(sz)])  # лямбда под windows, т.к. urandom'а в винде нет
from sys import argv, exit  # аргументы к проге и выход

if len(argv) != 3:  # +1 имя скрипта (-1, если будете замораживать)
    print('Usage: python3 WAV.py [num of samples] [output]')
    exit(1)

Στη συνέχεια πρέπει να δημιουργήσουμε όλες τις απαραίτητες μεταβλητές από τον πίνακα σύμφωνα με τα μεγέθη τους. Οι μη σταθερές τιμές σε αυτό εξαρτώνται εδώ μόνο από τα numSamples (τον αριθμό των δειγμάτων). Όσο περισσότερα από αυτά, τόσο περισσότερο θα διαρκέσει ο θόρυβος μας.

numSamples = int(argv[1])
output_path = argv[2]

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'x10x00x00x00'  # 0d16
audioFormat = b'x01x00'
numChannels = b'x02x00'  # 2-х каналов будет достаточно (стерео)
sampleRate = pack('<L', 1000)  # 1000 хватит, но если поставить больше, то шум будет слышен лучше. С 1000-ю он звучит, как ветер
bitsPerSample = b'x20x00'  # 0d32
byteRate = pack('<L', 1000 * 2 * 4)  # sampleRate * numChannels * bitsPerSample / 8  (32 bit sound)
blockAlign = b'x08x00'  # numChannels * BPS / 8
subchunk2ID = b'data'
subchunk2Size = pack('<L', numSamples * 2 * 4)  # * numChannels * BPS / 8
chunkSize = pack('<L', 36 + numSamples * 2 * 4)  # 36 + subchunk2Size

data = urandom(1000 * 2 * 4 * numSamples)  # сам шум

Το μόνο που μένει είναι να τα γράψετε με την απαιτούμενη σειρά (όπως στον πίνακα):

with open(output_path, 'wb') as fh:
    fh.write(chunkId + chunkSize + Format + subchunk1ID +
            subchunk1Size + audioFormat + numChannels + 
            sampleRate + byteRate + blockAlign + bitsPerSample +
            subchunk2ID + subchunk2Size + data)  # записываем

Και έτσι, έγινε. Για να χρησιμοποιήσουμε το σενάριο, πρέπει να προσθέσουμε τα απαραίτητα ορίσματα της γραμμής εντολών:
python3 WAV.py [num of samples] [output]
αριθμός δειγμάτων — κολ. δείγματα
έξοδος — διαδρομή προς το αρχείο εξόδου

Ακολουθεί ένας σύνδεσμος προς ένα δοκιμαστικό αρχείο ήχου με θόρυβο, αλλά για να εξοικονομήσω μνήμη μείωσα το BPS στο 1b/s και τον αριθμό των καναλιών στο 1 (με μια ασυμπίεστη ροή στερεοφωνικού ήχου 32 bit στα 64 kbs, πήρα 80M καθαρού αρχείου .wav και με αυτόν τον τρόπο μόνο 10): https://instaud.io/3Dcy

Ολόκληρος ο κώδικας (WAV.py) (Ο κώδικας έχει πολλές διπλότυπες τιμές μεταβλητών, αυτό είναι απλώς ένα σκίτσο):

from struct import pack  # перевод py-объектов в базовые типы из C
from os import urandom  # функция для чтения /dev/urandom, для windows:
# from random import randint
# urandom = lambda sz: bytes([randint(0, 255) for _ in range(sz)])  # лямбда под windows, т.к. urandom'а в винде нет
from sys import argv, exit  # аргументы к проге и выход

if len(argv) != 3:  # +1 имя скрипта (-1, если будете замораживать)
    print('Usage: python3 WAV.py [num of samples] [output]')
    exit(1)

numSamples = int(argv[1])
output_path = argv[2]

chunkId = b'RIFF'
Format = b'WAVE'
subchunk1ID = b'fmt '
subchunk1Size = b'x10x00x00x00'  # 0d16
audioFormat = b'x01x00'
numChannels = b'x02x00'  # 2-х каналов будет достаточно (стерео) 
sampleRate = pack('<L', 1000)  # 1000 хватит, но можно и больше.
bitsPerSample = b'x20x00'  # 0d32
byteRate = pack('<L', 1000 * 2 * 4)  # sampleRate * numChannels * bitsPerSample / 8  (32 bit sound)
blockAlign = b'x08x00'  # numChannels * BPS / 8
subchunk2ID = b'data'
subchunk2Size = pack('<L', numSamples * 2 * 4)  # * numChannels * BPS / 8
chunkSize = pack('<L', 36 + numSamples * 2 * 4)  # 36 + subchunk2Size

data = urandom(1000 * 2 * 4 * numSamples)  # сам шум

with open(output_path, 'wb') as fh:
    fh.write(chunkId + chunkSize + Format + subchunk1ID +
            subchunk1Size + audioFormat + numChannels + 
            sampleRate + byteRate + blockAlign + bitsPerSample +
            subchunk2ID + subchunk2Size + data)  # записываем в файл результат

Σύνολο

Τώρα ξέρετε λίγα περισσότερα για τον ψηφιακό ήχο και τον τρόπο αποθήκευσης του. Σε αυτήν την ανάρτηση δεν χρησιμοποιήσαμε συμπίεση (audioFormat), αλλά για να εξετάσουμε καθένα από τα δημοφιλή, θα απαιτηθούν 10 άρθρα. Ελπίζω να μάθατε κάτι νέο για τον εαυτό σας και αυτό θα σας βοηθήσει στις μελλοντικές εξελίξεις.
Σας ευχαριστούμε!

πηγές

Δομή αρχείου WAV
WAV - Wikipedia

Πηγή: www.habr.com

Αγοράστε αξιόπιστη φιλοξενία για ιστότοπους με προστασία DDoS, διακομιστές VPS VDS 🔥 Αγοράστε αξιόπιστη φιλοξενία ιστοσελίδων με προστασία DDoS, διακομιστές VPS VDS | ProHoster