Как сгенерировать .wav файл?
Допустим, мне нужно создать .wav файл, имеющий несколько значений частоты (в Гц) и длительности (в миллисекундах). Как мне его создать, имея массив значений, допустим
[1000,3000,5000,7000,8000]
или
[100,200]
, и массив длительности, допустим
[1000,1000,2000,3000,1000]
или
[1000,1]
?
Ответы (1 шт):
Я когда-то писал скрипт для подобной задачи.
Если что-то будет не понятно, то вот ссылка на подробное описание wav-формата http://microsin.net/programming/pc/wav-format.html
Примечание: этот скрипт работает с входными данными в виде списка целых чисел от 0 до 255, где каждое значение - значение звукового сигнала, и таких значений 44100 за секунду. Соответственно, вам нужно будет сгенерировать список этих значений из ваших частот и длительностей. Я привёл пример генерации данных для прямоугольной волны длительностью 1 секунда и частотой 220 герц.
from typing import List
CHUNK_ID = 'RIFF'
FORMAT = 'WAVE'
SUB_CHUNK_1_ID = 'fmt '
SUB_CHUNK_1_SIZE = 16
AUDIO_FORMAT = 1
NUM_CHANNELS = 1
SAMPLE_RATE = 44100
BITS_PER_SAMPLE = 8
BLOCK_ALIGN = int((BITS_PER_SAMPLE / 8) * NUM_CHANNELS)
AVG_BYTES_PER_SECOND = SAMPLE_RATE * BLOCK_ALIGN
SUB_CHUNK_2_ID = 'data'
def bytes_with_align(value, num_bytes):
if isinstance(value, int):
return value.to_bytes(num_bytes, byteorder='little')
assert num_bytes >= len(value)
bytes_value = bytes(value, encoding='ASCII')
rest = b'\x00' * (num_bytes - len(bytes_value))
return rest + bytes_value
def make_file_data(data: List[int]):
sub_chunk_2_size = len(data)
chunk_size = 36 + sub_chunk_2_size # file size minus chunk_id and format parts
# header_parts: (value, byte_size)
header = (
(CHUNK_ID, 4),
(chunk_size, 4),
(FORMAT, 4),
(SUB_CHUNK_1_ID, 4),
(SUB_CHUNK_1_SIZE, 4),
(AUDIO_FORMAT, 2),
(NUM_CHANNELS, 2),
(SAMPLE_RATE, 4),
(AVG_BYTES_PER_SECOND, 4),
(BLOCK_ALIGN, 2),
(BITS_PER_SAMPLE, 2),
(SUB_CHUNK_2_ID, 4),
(sub_chunk_2_size, 4),
)
header_bytes = b''.join(bytes_with_align(*part) for part in header)
file_data = header_bytes + b''.join(sample.to_bytes(int(BITS_PER_SAMPLE/8), byteorder='little') for sample in data)
return file_data
# Работать с этим так:
duration = 1 # Файл длиной 1 секунда
freq = 220 # Звук частотой 220 герц
period = 44100 / freq
seq_size = duration * 44100
data = [0 if (x % period < period/2) else 255 for x in range(seq_size)]
with open('test.wav', 'wb') as f:
f.write(make_file_data(data))