صدای بوق ممتد از لحاظ فنی همان موج سینوسی با فرکانسی (بسامد) ثابت است. در این مطلب یک کد ساده و کوتاه پایتون ارائه میدهم که بدون استفاده از کتابخانههای اضافی، میتواند یک بوق را با هر فرکانسی تولید کند و در یک فایل صوتی wave ذخیره کند.
import wave
import struct
import math
def gen_sine(t, freq):
return math.sin(2 * freq * t)
w = wave.open("sine.wav", "w")
w.setsampwidth(2)
w.setframerate(8000)
w.setnchannels(1)
freq = 4600
for t in range(18000):
r = int(gen_sine(t, freq) * 2**15)
b = struct.pack("<h", r)
w.writeframes(b)
w.close()
همانطور که در کد بالا مشاهده میکنید تنها سه کتابخانه که از کتابخانههایی هستند که معمولاً همراه پایتون ارائه میشوند، استفاده شده است.
- متغیر
freq
فرکانس بوق تولیدی را مشخص میکند. - ماژول wave برای نوشتن یک فایل صوتی wave که فایلی خام است استفاده شده است.
- همانطور که میبینید، طول هر نمونه ۲ بایت میباشد و هر نمونه یک عدد صحیح علامتدار ۱۶ بیتی است.
- تعداد کانالها تک است و در نتیجه صدای راست و چپ نداریم. اصطلاحاً فایل صوتی مونو تولید میشود.
- ۸۰۰۰ نمونه در یک ثانیه وجود دارد.
- حلقهٔ
for
تعداد ۱۸۰۰۰ نمونه تولید میکند و با توجه به وجود ۸۰۰۰ نمونه در یک ثانیه، فایل تولیدی کمی بیشتر از ۲ ثانیه خواهد بود. - ابتدا با استفاده از تابع
gen_sine
براساس زمان فعلی (یا دقیقتر: شمارهٔ نمونه فعلی) و فرکانس مقدار عددی نمونه را محاسبه میکند. - با توجه به این که مقدار محاسبه شدهٔ این تابع یک عدد اعشاری است و با یک عدد صحیح ۱۶ بیتی نیاز داریم، خروجی تابع در ۳۲۷۶۸ (یا ۲ به توان ۱۵) ضرب میشود و قسمت اعشاریاش دور انداخته میشود.
- سپس با استفاده از تابع
pack
از ماژولstruct
عدد صحیح به بایت تبدیل میشود. علامت «کوچکتر از» نشاندهنده little endian بودن بایتهای تولیدی است. همچین حرفh
نشاندهندهٔ این است که ورودی تابعpack
یک عدد صحیح ۱۶ بیتی علامتدار است. - نهایتاً فریمهای تولیدی به روی فایل صوتی نوشته میشوند و در نهایت فایل بسته میشود.