Генерация и сохранение звукового сигнала с заданной частотой на Python

В этой статье мы рассмотрим, как сгенерировать звуковой сигнал с заданной частотой и сохранить его в WAV-файл с помощью Python и популярных библиотек. Сгенерированный звук может быть использован в различных приложениях, таких как тестирование звукового оборудования, создание звуковых эффектов или образовательные цели.

Для генерации и сохранения звука мы будем использовать следующие библиотеки Python:

  • NumPy: Библиотека для работы с многомерными массивами данных, которая предоставляет мощные функции для математических операций.
  • wave: Стандартная библиотека Python для работы с WAV-файлами, позволяющая читать и записывать звуковые данные.
Генерация звукового сигнала

Звуковой сигнал представляет собой колебания давления воздуха, которые воспринимаются человеческим ухом. Синусоидальный сигнал является одним из основных типов звуковых волн, и мы будем использовать его для генерации звука с заданной частотой.

Для генерации сигнала мы будем использовать библиотеку NumPy, которая позволяет легко создавать массивы данных. Мы определим продолжительность сигнала, его частоту и частоту дискретизации (sampling rate), которая соответствует частоте, с которой звуковая карта или другое устройство будет воспроизводить звук.

import numpy as np

# Параметры звука
duration = 1  # Продолжительность в секундах
frequency = 1000  # Частота сигнала в герцах
sampling_rate = 44100  # Частота дискретизации

Затем сгенерируем массив данных, представляющий сигнал:

num_samples = int(duration * sampling_rate)
t = np.linspace(0, duration, num_samples, False)
signal = np.sin(2 * np.pi * frequency * t)

Здесь мы создаем массив t, содержащий временные отметки, и массив signal, содержащий значения сигнала в эти моменты времени.

Нормализация сигнала

Чтобы сигнал соответствовал 16-битному диапазону, используемому в WAV-файлах, мы нормализуем его. Нормализация гарантирует, что амплитуда сигнала не превышает максимального значения для 16-битного сэмпла.

signal_max = np.amax(np.abs(signal))
if signal_max > 0:
    signal *= 32767 / signal_max

Сохранение в WAV-файл

Для сохранения сгенерированного сигнала в WAV-файл мы используем библиотеку wave. WAV-файл хранит звуковые данные в виде последовательности сэмплов, и мы должны указать параметры, такие как количество каналов, размер сэмпла и частота дискретизации.

import wave

wav_file = wave.open("output_sound.wav", "w")
wav_file.setnchannels(1)  # Моно
wav_file.setsampwidth(2)  # 16-битный сэмпл
wav_file.setframerate(sampling_rate)
wav_file.writeframes(signal.astype(np.int16).tobytes())
wav_file.close()

Здесь мы открываем WAV-файл для записи, устанавливаем параметры и записываем сгенерированный сигнал. В конце не забываем закрыть файл.

После выполнения кода вы получите WAV-файл с именем output_sound.wav, содержащий сгенерированный звуковой сигнал. Вы можете воспроизвести этот файл с помощью любого проигрывателя аудио или использовать его в своих проектах.

Чтобы сгладить звуковой сигнал на старте и в конце, мы можем применить окно сглаживания (windowing) к сгенерированному массиву данных. Окно сглаживания позволяет постепенно увеличивать и уменьшать амплитуду сигнала, что приводит к более плавному началу и концу.

Одним из распространенных окон сглаживания является окно Ханнинга (Hann window), которое мы будем использовать в этом примере. Окно Ханнинга обеспечивает плавное повышение и понижение амплитуды, что приводит к более естественному звучанию.

Ниже представлен обновленный код с применением окна Ханнинга:

import numpy as np
import wave

# Параметры звука
duration = 1  # Продолжительность в секундах
frequency = 1000  # Частота сигнала в герцах
sampling_rate = 44100  # Частота дискретизации

# Генерация синусоидального сигнала
num_samples = int(duration * sampling_rate)
t = np.linspace(0, duration, num_samples, False)
signal = np.sin(2 * np.pi * frequency * t)

# Применение окна Ханнинга для сглаживания
window = np.hanning(num_samples)
signal *= window

# Нормализация сигнала
signal_max = np.amax(np.abs(signal))
if signal_max > 0:
    signal *= 32767 / signal_max

# Сохранение в WAV-файл
wav_file = wave.open("output_sound.wav", "w")
wav_file.setnchannels(1)  # Моно
wav_file.setsampwidth(2)  # 16-битный сэмпл
wav_file.setframerate(sampling_rate)
wav_file.writeframes(signal.astype(np.int16).tobytes())
wav_file.close()

print("Звук сохранен в файл output_sound.wav")

В этом коде мы добавили окно Ханнинга, умножив массив signal на массив window, который имеет ту же длину, что и массив данных. Это приводит к сглаживанию сигнала на старте и в конце.

Окно Ханнинга имеет форму полукосинуса, что обеспечивает плавное повышение и понижение амплитуды. Это позволяет избежать резких переходов в начале и конце сигнала, делая его более приятным на слух.

После выполнения этого кода вы должны получить WAV-файл с более плавным началом и окончанием звука.

В этой статье мы рассмотрели, как сгенерировать звуковой сигнал с заданной частотой и сохранить его в WAV-файл. Используя библиотеки NumPy и wave, мы можем создавать и сохранять звуковые данные для различных целей. Этот подход может быть полезен в образовательных, научных и развлекательных проектах, связанных со звуком.