تجزیه و تحلیل داده های صوتی در زمان های اخیر بسیار پر استفادهتر شده است. دستیارهای مجازی صوتی بسیار محبوبی توسط شرکت های بزرگ فناوری عرضه شده اند و این محصولات هر روز بیشتر و بیشتر در گوشی های هوشمند و خانه های هوشمند در سراسر جهان مورد استفاده قرار می گیرند.
طیف وسیعی از برنامه های کاربردی با استفاده از تجزیه و تحلیل داده های صوتی وجود دارد، و این یک موضوع غنی برای بررسی است. در این مقاله، ما بر روی یک بخش اساسی از فرآیند تجزیه و تحلیل داده های صوتی تمرکز می کنیم: رسم شکل موج و طیف فرکانس فایل صوتی.
باز کردن یک فایل WAV
فایل های صوتی در فرمت های مختلفی وجود دارند. احتمالاً با MP3 آشنا هستید که از فشرده سازی lossy برای ذخیره داده ها استفاده می کند. فرمتهایی مانند FLAC از فشردهسازی lossless استفاده میکنند که اجازه میدهد تا دادههای اصلی را به طور کامل از روی دادههای فشرده بازسازی کنیم. فایل صوتی ما که در این مقاله روی آن کار می کنیم با فرمت WAV (Waveform Audio File) است که فشرده نشده است. در نتیجه اندازه فایل می تواند بزرگ باشد.
فایل صوتی که آن را بررسی خواهیم کرد یک آهنگ شاد است که با پیانو شروع می شود. صداهای دیگری مانند صدای زنگ و کف زدن در سرتاسر صدای این آهنگ به گوش میرسد، به همراه یک قطعه گیتار در دو نقطه از آهنگ. ذکر این ویژگیها در ضبط صدا خالی از لطف نیست زیرا بعداً وقتی شکل موج و طیف فرکانس را ترسیم میکنیم، میتوانیم برخی از این صدا ها را شناسایی کنیم.
برای باز کردن فایل WAV از ماژول WAVE در پایتون استفاده می کنیم که به صورت زیر قابل ایمپورت و فراخوانی است:
>>> import wave
>>> wav_obj = wave.open('file.wav', 'rb')
حالت “rb
” یک شیء wave_read
را برمی گرداند. استفاده از “wb
” برای باز کردن فایل، یک شیء wave_write
را برمی گرداند که متدهای متفاوتی با شیء قبلی دارد. همانطور که در اینجا نشان می دهیم می توانید از یک دستور with
برای باز کردن فایل استفاده کنید.
مقاله پیشنهادی: آموزش نحوه تغییر نام گروهی فایل ها با پایتون در کامپیوتر
موج صوتی یک کمیت پیوسته است که برای دیجیتالی کردن آن باید در یک بازه زمانی نمونه برداری شود. نرخ نمونه برداری، تعداد نمونه هایی از صدا را در هر ثانیه مشخص می کند. با استفاده از متد زیر می توانیم به این اطلاعات دسترسی پیدا کنیم:
sample_freq = wav_obj.getframerate()
sample_freq
#44100
فرکانس نمونه، تعداد نمونه ها را در هر ثانیه اندازه گیری می کند. در این حالت 44100 بار در ثانیه است که با کیفیت CD مطابقت دارد. تعداد فریمها یا نمونهها به صورت زیر به دست میآید:
n_samples = wav_obj.getnframes()
n_samples
#5384326
اکنون می توانیم مدت زمان فایل صوتی خود را بر حسب ثانیه محاسبه کنیم:
t_audio = n_samples/sample_freq
t_audio
#122.09356009070295
فایل صوتی به صورت استریو، یعنی در دو کانال صوتی مستقل ضبط می شود. این احساس را ایجاد می کند که صدا از دو جهت مختلف می آید. می توانیم تعداد کانال ها را به صورت زیر بررسی کنیم:
n_channels = wav_obj.getnchannels()
n_channels
#2
مرحله بعدی بدست آوردن مقادیر سیگنال، یعنی دامنه موج در هر نقطه از زمان است. برای انجام این کار، میتوانیم از متد readframes()
استفاده کنیم که یک آرگومان (n) می گیرد که برای تعیین تعداد فریمهایی که میخواهیم بخوانیم است:
signal_wave = wav_obj.readframes(n_samples)
این متد یک شیء بایت را برمی گرداند. می توانید با استفاده از تابع داخلی type()
روی شیء signal_wave
، آن را بررسی کنید. برای دریافت مقادیر سیگنال از این شیء، باید به numpy روی آوریم:
import numpy as np
signal_array = np.frombuffer(signal_wave, dtype=np.int16)
این متد همه داده ها را از هر دو کانال به صورت یک آرایه 1 بعدی برمی گرداند. اگر شکل signal_array
را بررسی کنید ، متوجه می شوید که دارای 10,768,652 عنصر است که دقیقاً برابر است با n_samples * n_channels
. برای تقسیم دادهها به کانالهای جداگانه، میتوانیم از ترفند کوچک و هوشمندانه برش آرایه استفاده کنیم:
l_channel = signal_array[0::2]
r_channel = signal_array[1::2]
در حال حاضر، کانال های چپ و راست ما از هم جدا شده اند، هر دو شامل 5،384،326 عدد صحیح هستند که نشان دهنده دامنه سیگنال هستند.
در مرحله بعد، چند نمونه از نحوه رسم مقادیر سیگنال را نشان می دهیم. ما در اینجا داده های خود را در آرایه ها ذخیره می کنیم، اما برای بسیاری از کاربردهای علم داده، pandas بسیار مفیدتر است. این مقاله را که در مورد تجسم داده های ذخیره شده در یک DataFrame
است بررسی کنید.
ترسیم دامنه سیگنال
قبل از اینکه به ترسیم مقادیر سیگنال بپردازیم، باید زمان برداشت هر نمونه را محاسبه کنیم. که به سادگی برابر است با کل طول مسیر بر حسب ثانیه تقسیم بر تعداد نمونه ها. برای ایجاد آرایه ای از گامهای زمانی می توانیم از تابع linspace()
از numpy
استفاده کنیم:
times = np.linspace(0, n_samples/sample_freq, num=n_samples)
برای رسم، از کلاس pyplot
از matplotlib
استفاده می کنیم. اگر به مطالب پیشنیاز برای ترسیم در پایتون نیاز دارید، قسمت 1 و قسمت 2 از مقدمه ای matplotlib
را مطالعه کنید. در این دو مقاله نحوه ترسیم چندین نوع نمودار های مرسوم توضیح داده شده است.
برای سادگی، در اینجا فقط سیگنال را از یک کانال رسم می کنیم. در کد زیر، اندازه نمودار و عنوان و برچسب ها را تنظیم می کنیم و سری زمانی را به صورت زیر ترسیم کنیم:
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 5))
plt.plot(times, l_channel)
plt.title('Left Channel')
plt.ylabel('Signal Value')
plt.xlabel('Time (s)')
plt.xlim(0, t_audio)
plt.show()
شکل زیر در یک پنجره جدید باز میشود:
ما شاهد افزایش دامنه در 6 ثانیه اول هستیم، در این مرحله اثرات زنگ و کف زدن شروع می شود. دو مکث کوتاه در 31.5 و 44.5 ثانیه وجود دارد که در مقادیر سیگنال مشهود است. پس از مکث دوم، ساز اصلی به طور متناوب بین گیتار و پیانو جا به جا می شود که تقریباً در سیگنال دیده می شود، و در آن قسمت گیتار دامنه های کمتری دارد. سپس، در انتهای مسیر، یک خروجی با دامنه کمتر وجود دارد. اینجا جاییست که آهنگ به آرامی تمام می شود.
رسم طیف فرکانس
حال، بیایید نگاهی به طیف فرکانس، که به عنوان طیفنگار نیز شناخته میشود، بیاندازیم. این یک نمایش بصری از قدرت سیگنال در فرکانسهای مختلف است که به ما نشان میدهد کدام فرکانسها بر حسب زمان در آهنگ غالب هستند:
plt.figure(figsize=(15, 5))
plt.specgram(l_channel, Fs=sample_freq, vmin=-20, vmax=50)
plt.title('Left Channel')
plt.ylabel('Frequency (Hz)')
plt.xlabel('Time (s)')
plt.xlim(0, t_audio)
plt.colorbar()
plt.show()
نمودار زیر در یک پنجره جدید باز می شود:
در کد بالا، vmin و vmax انتخاب شدهاند تا فرکانسهای پایینتری را که بر این ضبط غالب هستند، نشان دهند. در واقع، فرکانس های غالب برای کل مسیر کمتر از 2.5 کیلوهرتز است. شما اثر سازهای مختلف و جلوه های صوتی را مشاهده می کنید، به خصوص در محدوده فرکانسی حدود 10 کیلوهرتز تا 15 کیلوهرتز. هر ساز و افکت صوتی دارای امضای خاص خود در طیف فرکانس است.
چطور صداها رو میشه تغییر داد.وی است تی اصلان نمیتونه صدا رو تغییر بده
سلام.
یک مطلب در این مورد منتشر کردم بخونیدش:
https://bkeb.ir/?p=48961
کد ها رو تست کنید در صورتی که مشکلی داشتید بپرسید.