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

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

Ιστορία

Το WAVE (Waveform Audio File Format) είναι μια μορφή αρχείου κοντέινερ για την αποθήκευση μιας εγγραφής ροής ήχου. Αυτό το δοχείο χρησιμοποιείται συνήθως για την αποθήκευση μη συμπιεσμένου ήχου PCM. (Λήψη από τη 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 ανά 1 δείγμα (βάθος)
Οποιοσδήποτε αριθμός είναι πολλαπλάσιο του 8. Όσο περισσότερο, τόσο καλύτερος και βαρύτερος θα είναι ο ήχος, δεν υπάρχει διαφορά από τα 32 bit για ένα άτομο

subchunk2Id
4
Το σημείο εκκίνησης των δεδομένων (επειδή ενδέχεται να υπάρχουν άλλα στοιχεία κεφαλίδας ανάλογα με τη μορφή ήχου)
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

Προσθέστε ένα σχόλιο