ΠΠ΄ΡΠ°Π²ΡΡΠ²ΡΠΉΡΠ΅! ΠΠΎΡ ΠΏΠ΅ΡΠ²Π°Ρ ΡΠ΅ΡΠΈΡ ΡΡΠ°ΡΠ΅ΠΉ Π±ΡΠ΄Π΅Ρ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½Π° Π½Π° ΠΈΠ·ΡΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΡΠΆΠ°ΡΠΈΡ ΠΈ Ρ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ/Π·Π²ΡΠΊΠ°, ΡΠ°ΠΊΠΈΡ ΠΊΠ°ΠΊ JPEG (ΠΈΠ·ΠΎΠ±Ρ.) ΠΈ WAVE (Π·Π²ΡΠΊ), ΡΠ°ΠΊΠΆΠ΅ Π² Π½ΠΈΡ Π±ΡΠ΄ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΠΈΡ ΡΠΎΡΠΌΠ°ΡΠΎΠ² (.jpg, .wav) Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅. Π ΡΡΠΎΠΉ ΡΠ°ΡΡΠΈ ΠΌΡ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΈΠΌΠ΅Π½Π½ΠΎ WAVE.
Cerita
WAVE (Waveform Audio File Format) adalah format file kontainer untuk menyimpan rekaman aliran audio. Wadah ini biasanya digunakan untuk menyimpan audio termodulasi kode pulsa yang tidak terkompresi. (Diambil dari Wikipedia)
Ini ditemukan dan diterbitkan pada tahun 1991 bersama dengan RIFF oleh Microsoft dan IBM (Perusahaan IT terkemuka saat itu).
Struktur file
File tersebut memiliki bagian header, datanya sendiri, tetapi tidak ada footer. Header memiliki berat total 44 byte.
Header berisi pengaturan jumlah bit dalam sampel, laju sampel, kedalaman suara, dll. informasi yang diperlukan untuk kartu suara. (Semua nilai tabel numerik harus ditulis dalam urutan Little-Endian)
Nama blok
Ukuran blok (B)
Deskripsi/Tujuan
Nilai (untuk beberapa hal itu tetap
potonganId
4
Mendefinisikan file sebagai wadah media
0x52494646 dalam Big-Endian (βRIFFβ)
ukuran potongan
4
Ukuran seluruh file tanpa chunkId dan chunkSize
UKURAN_FILE - 8
format
4
Ketik definisi dari RIFF
0x57415645 dalam Big-Endian (βGELOMBANGβ)
subchunk1Id
4
Sehingga file tersebut memakan lebih banyak ruang sebagai kelanjutan formatnya
0x666d7420 dalam Big-Endian (βfmtβ)
subchunk1Ukuran
4
Header yang tersisa (dalam byte)
16 secara default (untuk kasus tanpa kompresi aliran audio)
format audio
2
ΠΡΠ΄ΠΈΠΎ ΡΠΎΡΠΌΠ°Ρ (Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΠΌΠ΅ΡΠΎΠ΄Π° ΡΠΆΠ°ΡΠΈΡ ΠΈ ΡΡΡΡΠΊΡΡΡΡ Π°ΡΠ΄ΠΈΠΎΠ΄Π°Π½Π½ΡΡ
)
1 (untuk PCM, itulah yang kami pertimbangkan)
nomor saluran
2
Jumlah saluran
1/2, kita akan mengambil 1 saluran (3/4/5/6/7... - trek audio tertentu, misalnya 4 untuk audio quad, dll.)
tingkat sampel
4
Kecepatan pengambilan sampel audio (dalam Hertz)
Semakin tinggi, semakin baik suaranya, tetapi semakin banyak memori yang dibutuhkan untuk membuat trek audio dengan panjang yang sama, nilai yang disarankan adalah 48000 (kualitas suara yang paling dapat diterima)
byteRate
4
Jumlah byte per detik
tingkat sampel nomor saluran bitsPerSample (lebih lanjut)
blokSejajarkan
2
Jumlah byte untuk 1 sampel
numChannels * bitPerSample: 8
bitPerSample
2
Jumlah bit per 1 sampel (kedalaman)
Angka apa pun yang merupakan kelipatan 8. Semakin tinggi angkanya maka audionya akan semakin bagus dan berat, dari 32 bit tidak ada bedanya bagi manusia
subchunk2Id
4
Tanda referensi data (karena mungkin ada elemen header lain bergantung pada format audio)
0x64617461 dalam Big-Endian("data")
subchunk2Ukuran
4
Ukuran area data
ukuran data dalam int
data
byteRate * durasi audio
data audio
?
Contoh GELOMBANG
Tabel sebelumnya dapat dengan mudah diterjemahkan ke dalam struktur dalam C, tetapi bahasa kita saat ini adalah Python. Hal termudah yang dapat Anda lakukan adalah menggunakan βgelombangβ - generator kebisingan. Untuk tugas ini kita tidak memerlukan byteRate dan kompresi yang tinggi.
Pertama, mari impor 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 jumlahnya, semakin lama kebisingan kita berlangsung.
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) # ΡΠ°ΠΌ ΡΡΠΌ
Yang tersisa hanyalah 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) # Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ
Jadi, siap. Untuk menggunakan skrip, kita perlu menambahkan argumen baris perintah yang diperlukan:
python3 WAV.py [num of samples] [output]
jumlah sampel - hitung. sampel
keluaran β jalur ke file keluaran
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 aliran audio stereo 32-bit yang tidak terkompresi pada 64kbs, ternyata menjadi 80M file .wav murni, dan hanya 10):
Seluruh kode (WAV.py) (Kode memiliki banyak nilai variabel duplikat, 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'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) # Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ Π² ΡΠ°ΠΉΠ» ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ
Total
Jadi, Anda telah belajar lebih banyak tentang suara digital dan cara penyimpanannya. Pada postingan kali ini kami tidak menggunakan kompresi (audioFormat), namun untuk mempertimbangkan masing-masing yang populer, diperlukan 10 artikel. Saya harap Anda mempelajari sesuatu yang baru untuk diri Anda sendiri dan ini akan membantu Anda dalam pengembangan di masa mendatang.
Terima kasih!
sumber
Sumber: www.habr.com