Metode kompresi / penyimpanan media dalam WAVE dan JPEG, bagian 1

Halo Seri artikel pertama saya akan ditujukan untuk mempelajari metode mengompresi dan menyimpan gambar / suara, seperti JPEG (gambar) dan WAVE (suara), dan mereka juga akan memasukkan contoh program menggunakan format ini (.jpg, .wav) dalam praktiknya. Pada bagian ini kami akan mempertimbangkan WAVE.


Ceritanya


WAVE (Waveform Audio File Format) adalah format file kontainer untuk menyimpan rekaman stream audio. Wadah ini biasanya digunakan untuk menyimpan suara yang tidak dikompresi dalam modulasi kode pulsa. (Diadaptasi dari Wikipedia)

Itu diciptakan dan diterbitkan pada tahun 1991 bersama dengan RIFF oleh Microsoft dan IBM (Perusahaan IT terkemuka saat itu).


Struktur file


File memiliki bagian header, data itu sendiri, tetapi tidak ada footer. Header memiliki berat total 44 byte.
Header berisi pengaturan untuk jumlah bit dalam sampel, frekuensi descritization, kedalaman suara, dll. informasi yang diperlukan untuk kartu suara. (Semua nilai tabel numerik harus ditulis dalam urutan Little-Endian)


Nama blokirUkuran blok (B)Deskripsi / TujuanNilai (untuk beberapa itu sudah diperbaiki
chunkId4Mendefinisikan file sebagai wadah media0x52494646 di Big-Endian ("RIFF")
potongan4Ukuran seluruh file tanpa chunkId dan chunkSizeFILE_SIZE - 8
format4Ketikkan definisi dari RIFF0x57415645 di Big-Endian ("WAVE")
subchunk1Id4Untuk mengambil lebih banyak ruang file format lanjutan0x666d7420 di Big-Endian ("fmt")
subchunk1Size4Header yang tersisa (dalam byte)16 secara default (untuk kasing tanpa kompresi aliran audio)
audioFormat2Format audio (tergantung pada metode kompresi dan struktur data audio)1 (untuk PCM, yang sedang kami pertimbangkan)
saluran num2Jumlah saluran1/2, kami mengambil 1 saluran (3/4/5/6/7 ... - trek audio tertentu, misalnya 4 untuk suara quad, dll.)
sampleRate4Frekuensi pengambilan sampel suara (dalam Hertz)Semakin banyak, semakin baik suaranya, tetapi semakin banyak memori yang diperlukan untuk membuat trek audio dengan panjang yang sama, nilai yang disarankan adalah 48000 (kualitas suara paling dapat diterima)
byteRate4Jumlah byte dalam 1 detiksampleRate numChannels bitsPerSample (selanjutnya)
blockAlign2Jumlah byte untuk 1 sampelnumChannels * bitsPerSampel: 8
bitsPerSample2Jumlah bit per 1 sampel (kedalaman)Angka apa pun yang merupakan kelipatan dari 8. Semakin besar audio akan semakin baik, dari 32 bit tidak ada perbedaan untuk seseorang.
subchunk2Id4Tanda referensi dari awal data (karena mungkin ada elemen header lainnya tergantung pada audioFormat)0x64617461 dalam Big-Endian ("data")
subchunk2Size4Ukuran Area Dataukuran data dalam int
databyteRate * durasi audioData audio?

WAVE contohnya


Tabel sebelumnya dapat dengan mudah diterjemahkan ke dalam struktur C, tapi hari ini bahasa kita adalah Python. Hal termudah untuk dilakukan menggunakan gelombang adalah generator kebisingan. Untuk tugas ini, kita tidak perlu byteRate dan kompresi tinggi.
Untuk memulai, kami mengimpor modul yang diperlukan:


# 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) 

Selanjutnya, kita perlu membuat semua variabel yang diperlukan dari tabel sesuai dengan ukurannya. Nilai variabel di dalamnya hanya bergantung pada numSamples (jumlah sampel). Semakin banyak, semakin lama kebisingan kita pergi.


 numSamples = int(argv[1]) output_path = argv[2] chunkId = b'RIFF' Format = b'WAVE' subchunk1ID = b'fmt ' subchunk1Size = b'\x10\x00\x00\x00' # 0d16 audioFormat = b'\x01\x00' numChannels = b'\x02\x00' # 2-    () sampleRate = pack('<L', 1000) # 1000 ,    ,     .  1000-  ,   bitsPerSample = b'\x20\x00' # 0d32 byteRate = pack('<L', 1000 * 2 * 4) # sampleRate * numChannels * bitsPerSample / 8 (32 bit sound) blockAlign = b'\x08\x00' # 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) #   

Tinggal menuliskannya dalam urutan yang diperlukan (seperti pada tabel):


 with open(output_path, 'wb') as fh: fh.write(chunkId + chunkSize + Format + subchunk1ID + subchunk1Size + audioFormat + numChannels + sampleRate + byteRate + blockAlign + bitsPerSample + subchunk2ID + subchunk2Size + data) #  

Dan, selesai. Untuk menggunakan skrip, kita perlu menambahkan argumen baris perintah yang diperlukan:
python3 WAV.py [num of samples] [output]
jumlah sampel - hitung sampel
output - path ke file output


Berikut ini tautan ke file audio uji dengan noise, tetapi untuk menghemat memori, saya menurunkan BPS ke 1b / s dan menurunkan jumlah saluran menjadi 1 (dengan streaming audio stereo 32-bit tanpa kompresi di 64kbs, kami mendapat file bersih .wav 80M, dan hanya 10): https: / /instaud.io/3Dcy


Seluruh kode (WAV.py) (kode memiliki banyak nilai duplikat variabel, ini hanya sketsa):


 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'\x10\x00\x00\x00' # 0d16 audioFormat = b'\x01\x00' numChannels = b'\x02\x00' # 2-    () sampleRate = pack('<L', 1000) # 1000 ,    . bitsPerSample = b'\x20\x00' # 0d32 byteRate = pack('<L', 1000 * 2 * 4) # sampleRate * numChannels * bitsPerSample / 8 (32 bit sound) blockAlign = b'\x08\x00' # 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) #     

Ringkasan


Jadi Anda belajar lebih banyak tentang suara digital dan bagaimana cara menyimpannya. Dalam posting ini kami tidak menggunakan kompresi (audioFormat), tetapi untuk meninjau setiap artikel populer Anda akan membutuhkan artikel 10. Saya harap Anda mempelajari sesuatu yang baru untuk diri Anda sendiri dan ini akan membantu Anda dalam pengembangan di masa depan.
Terima kasih


Sumber

Struktur file WAV
WAV - Wikipedia

Source: https://habr.com/ru/post/id450774/


All Articles