Repellent Digital Pakai ASDR
Pengusir Tikus Digital Pakai ASDR
Standar Frekwensi Sampel_Rate
sample_rate tidak hanya 44.1 kHz. Ada beberapa standar sample_rate yang umum digunakan, tergantung pada aplikasi audio. Berikut beberapa yang paling umum:
1. Standar CD dan Konsumen
- 44.1 kHz → CD Audio, MP3, sebagian besar file musik digital
- 48 kHz → Standar Broadcast, digunakan di video dan produksi film
- 32 kHz → Format audio kompresi rendah, digunakan di beberapa siaran radio
2. Standar Profesional dan Studio
- 96 kHz → Digunakan di studio rekaman untuk kualitas lebih tinggi
- 192 kHz → Audio berkualitas hi-res, sering digunakan dalam mastering dan rekaman profesional
3. Standar Audio Telepon dan Komunikasi
- 8 kHz → Telepon, VoIP (karena suara manusia cukup dalam rentang ini)
- 16 kHz → Suara lebih jernih untuk komunikasi, beberapa codec VoIP
- 22.05 kHz → Format audio untuk aplikasi kompresi tinggi
4. Standar untuk Ultrasonik & Riset
- 384 kHz dan lebih tinggi → Digunakan untuk ultrasonik, penelitian medis, dan beberapa DAC (Digital-to-Analog Converter) kelas atas
Jadi, 44.1 kHz bukan satu-satunya sample rate, dan pemilihan sample_rate harus disesuaikan dengan kebutuhan proyek audio yang dibuat. Untuk proyek frekuensi tinggi (seperti 33kHz - 77kHz), 192 kHz atau lebih tinggi direkomendasikan agar tidak terjadi aliasing.
Contoh Kode:
import numpy as np
from scipy.io.wavfile import write
# Fungsi untuk membuat envelope ASDR
def create_asdr_envelope(duration, sample_rate, attack_time=0.1, decay_time=0.1, sustain_level=0.7, release_time=0.2):
total_samples = int(sample_rate * duration)
attack_samples = int(sample_rate * attack_time)
decay_samples = int(sample_rate * decay_time)
release_samples = int(sample_rate * release_time)
sustain_samples = total_samples - (attack_samples + decay_samples + release_samples)
attack = np.linspace(0, 2.205, attack_samples) # Attack (Naik dari 0 ke 2.205)
decay = np.linspace(1, sustain_level, decay_samples) # Decay (Turun dari 1 ke sustain_level
sustain = np.ones(sustain_samples) * sustain_level # Sustain (Tetap di sustain_level)
release = np.linspace(sustain_level, 0, release_samples) # Release (Turun dari sustain_level ke 0)
envelope = np.concatenate((attack, decay, sustain, release))
if len(envelope) < total_samples:
envelope = np.pad(envelope, (0, total_samples - len(envelope)), mode='constant')
elif len(envelope) > total_samples:
envelope = envelope[:total_samples]
return envelope
# Fungsi untuk membuat sweep dengan ASDR & normalisasi yang aman
def save_sweep_wave_asdr(start_freq, end_freq, duration, file_name, sample_rate=44100, gain_db=10):
try:
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
freqs = np.linspace(start_freq, end_freq, int(sample_rate * duration))
waveform = 0.5 * np.sin(2 * np.pi * freqs * t)
# Terapkan envelope ASDR
envelope = create_asdr_envelope(duration, sample_rate)
waveform *= envelope
# Konversi gain dB ke faktor pengali
gain_factor = 10 ** (gain_db / 10)
waveform *= gain_factor
# Normalisasi (hindari pembagian oleh nol)
max_value = np.max(np.abs(waveform))
if max_value > 0:
waveform = np.int16(waveform / max_value * 32767)
else:
waveform = np.zeros_like(waveform, dtype=np.int16)
# Simpan file audio
write(file_name, sample_rate, waveform)
print(f"✅ Audio sweep disimpan sebagai: {file_name}")
except Exception as e:
print(f"❌ Gagal menyimpan file: {e}")
# Simpan sweep dari 33KHz ke 77KHz selama 60 detik dengan ASDR
save_sweep_wave_asdr(33000, 77000, 1/3, "/storage/emulated/0/Music/Frequency_Sweep_ASDR.wav")
Output:
❌ Gagal menyimpan file: negative dimensions are not allowed
[Program finished]
Hitung-hitungan:
Dari parameter-parameter yang digunakan pada kode pembuat repellent ini, bisa dbuat hitung-hitungannya kenapa hasilnya "negatif" (gagal membuat file wav).
Ada beberapa kemungkinan mengapa hasilnya bisa menjadi "negatif" atau tidak sesuai harapan dalam kode ini. Berikut adalah analisis hitung-hitungannya:
-
Kesalahan pada Attack Envelope
Pada baris ini:attack = np.linspace(0, 2.205, attack_samples) # Attack (Naik dari 0 ke 1)Nilai akhir attack adalah
2.205, bukan1, yang seharusnya digunakan untuk normalisasi amplitude ke rentang 0-1. Seharusnya:attack = np.linspace(0, 1, attack_samples)Kesalahan ini membuat nilai amplitudo melebihi 1, yang bisa menyebabkan distorsi atau hasil tidak normal.
-
Kesalahan Perhitungan Jumlah Sampel
Kita hitung total sample berdasarkan parameter:total_samples = int(sample_rate * duration) # 44100 * (1/3) = 14700 samplesAttack, decay, sustain, dan release masing-masing dihitung sebagai:
attack_samples = int(sample_rate * attack_time) # 44100 * 0.1 = 4410 decay_samples = int(sample_rate * decay_time) # 44100 * 0.1 = 4410 release_samples = int(sample_rate * release_time) # 44100 * 0.2 = 8820 sustain_samples = total_samples - (attack_samples + decay_samples + release_samples) # sustain_samples = 14700 - (4410 + 4410 + 8820) = -2940Masalahnya adalah sustain_samples menjadi negatif, yang menyebabkan
sustain = np.ones(sustain_samples) * sustain_levelgagal, karena array tidak bisa memiliki panjang negatif.Solusi: Pastikan
attack_time + decay_time + release_time <= duration, misalnya dengan menyesuaikanrelease_time. -
Kesalahan Normalisasi Gain
Gain dihitung sebagai:gain_factor = 10 ** (gain_db / 10)Dengan
gain_db = 10, maka:gain_factor = 10 ** (10 / 10) = 10Sehingga amplitudo diperbesar 10 kali lipat, menyebabkan clipping saat dikonversi ke
np.int16, yang seharusnya berada dalam rentang-32767hingga32767.Solusi: Gunakan perhitungan gain dalam dB SPL (Sound Pressure Level):
gain_factor = 10 ** (gain_db / 20) # Lebih aman untuk skala amplitudo -
Frekuensi Sweep Terlalu Tinggi
Sweep dilakukan dari33kHzke77kHz, sedangkan frekuensi sampling hanya 44.1kHz.
Nyquist theorem menyatakan bahwa sinyal yang memiliki frekuensi di atas sample_rate / 2 (22.05kHz) akan menyebabkan aliasing, sehingga frekuensi yang dimainkan tidak sesuai.Solusi: Pastikan frekuensi tidak melebihi 22kHz, atau tingkatkan
sample_rateke 192000 Hz.
Kesimpulan:
- Perbaiki nilai attack (jangan lebih dari 1).
- Perbaiki sustain_samples agar tidak negatif.
- Gunakan gain scaling yang aman (
10**(gain_db / 20)). - Pastikan sample rate cukup tinggi untuk menangani sweep frekuensi tinggi.
Perhitungan Envelope:
Mari kita hitung envelope ASDR berdasarkan parameter yang ada dalam kode:
1. Parameter yang Diketahui
- Sample rate = 44,100 Hz
- Durasi = detik (0.333 detik)
- Attack time = 0.1 detik
- Decay time = 0.1 detik
- Sustain level = 0.7
- Release time = 0.2 detik
Total sampel:
\text{total_samples} = \text{sample_rate} \times \text{duration} = 44100 \times 0.333 = 14700
2. Hitung Setiap Fase
- Attack samples:
\text{attack_samples} = \text{sample_rate} \times \text{attack_time} = 44100 \times 0.1 = 4410
\text{decay_samples} = \text{sample_rate} \times \text{decay_time} = 44100 \times 0.1 = 4410
\text{release_samples} = \text{sample_rate} \times \text{release_time} = 44100 \times 0.2 = 8820
\text{sustain_samples} = \text{total_samples} - (\text{attack_samples} + \text{decay_samples} + \text{release_samples})
\text{sustain_samples} = 14700 - (4410 + 4410 + 8820) = -2940 ]
Karena sustain_samples negatif, ini adalah kesalahan, karena tidak mungkin ada jumlah sampel negatif.
3. Kenapa Sustain Menjadi Negatif?
Total waktu dari attack + decay + release adalah:
0.1 + 0.1 + 0.2 = 0.4 \text{ detik}
4. Perbaikan Perhitungan
Untuk menghindari sustain negatif, total waktu ASDR harus ≤ durasi sinyal. Solusinya:
- Kurangi release → Misalnya release = 0.133 detik, agar totalnya 0.333 detik.
- Kurangi attack dan decay → Misalnya attack = 0.08 detik, decay = 0.08 detik, release = 0.173 detik.
Misalkan kita memilih opsi 1 (release = 0.133 detik):
- Attack:
- Decay:
- Release:
- Sustain:
14700 - (4410 + 4410 + 5865) = 15 \text{ (masih bisa dipakai)}
Sekarang sustain tidak negatif, dan envelope bisa dihitung dengan benar.
5. Perhitungan Envelope ASDR
Sekarang kita buat envelope dengan nilai yang benar:
- Attack (Naik dari 0 ke 1):
\text{attack} = np.linspace(0, 1, 4410)
\text{decay} = np.linspace(1, 0.7, 4410)
\text{sustain} = np.ones(15) \times 0.7
\text{release} = np.linspace(0.7, 0, 5865)
Kemudian digabungkan:
\text{envelope} = \text{np.concatenate}((\text{attack}, \text{decay}, \text{sustain}, \text{release}))
Kesimpulan
- Masalah utama: Sustain menjadi negatif karena durasi ASDR lebih besar dari durasi total.
- Solusi: Sesuaikan release, attack, atau decay agar total tidak melebihi durasi sinyal.
- Hasil envelope setelah diperbaiki: Attack naik ke 1, decay turun ke 0.7, sustain tetap, release turun ke 0 dalam waktu yang sesuai.
Perbaikan Sementara kode:
Dengan parameter:
- Sample rate = 44100 Hz
- Durasi = detik (1/2 detik)
- Attack time = 0.2 detik
- Decay time = 0.1 detik
- Sustain level = 0.7
- Release time = 0.173 detik
import numpy as np
from scipy.io.wavfile import write
# Fungsi untuk membuat envelope ASDR
def create_asdr_envelope(duration, sample_rate, attack_time=0.2, decay_time=0.1, sustain_level=0.7, release_time=0.173):
total_samples = int(sample_rate * duration)
attack_samples = int(sample_rate * attack_time)
decay_samples = int(sample_rate * decay_time)
release_samples = int(sample_rate * release_time)
sustain_samples = total_samples - (attack_samples + decay_samples + release_samples)
attack = np.linspace(0, 1, attack_samples) # Attack (Naik dari 0 ke 1)
decay = np.linspace(1, sustain_level, decay_samples) # Decay (Turun dari 1 ke sustain_level
sustain = np.ones(sustain_samples) * sustain_level # Sustain (Tetap di sustain_level)
release = np.linspace(sustain_level, 0, release_samples) # Release (Turun dari sustain_level ke 0)
envelope = np.concatenate((attack, decay, sustain, release))
if len(envelope) < total_samples:
envelope = np.pad(envelope, (0, total_samples - len(envelope)), mode='constant')
elif len(envelope) > total_samples:
envelope = envelope[:total_samples]
return envelope
# Fungsi untuk membuat sweep dengan ASDR & normalisasi yang aman
def save_sweep_wave_asdr(start_freq, end_freq, duration, file_name, sample_rate=44100, gain_db=10):
try:
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
freqs = np.linspace(start_freq, end_freq, int(sample_rate * duration))
waveform = 0.5 * np.sin(2 * np.pi * freqs * t)
# Terapkan envelope ASDR
envelope = create_asdr_envelope(duration, sample_rate)
waveform *= envelope
# Konversi gain dB ke faktor pengali
gain_factor = 10 ** (gain_db / 20)
waveform *= gain_factor
# Normalisasi (hindari pembagian oleh nol)
max_value = np.max(np.abs(waveform))
if max_value > 0:
waveform = np.int16(waveform / max_value * 32767)
else:
waveform = np.zeros_like(waveform, dtype=np.int16)
# Simpan file audio
write(file_name, sample_rate, waveform)
print(f"✅ Audio sweep disimpan sebagai: {file_name}")
except Exception as e:
print(f"❌ Gagal menyimpan file: {e}")
# Simpan sweep dari 33KHz ke 77KHz selama 1/2 detik dengan ASDR
save_sweep_wave_asdr(33000, 77000, 1/2, "/storage/emulated/0/Music/Frequency_Sweep_ASDR.wav")
Perbaikan Fix Kode:
Kemudian ketika frekwensi sampel_rate diubah dari 44100 Hz menjadi 192 KHz, maka menghasilkan audio wav seperti bunyi yang diharapkan:
Hasil kode:
import numpy as np
from scipy.io.wavfile import write
# Fungsi untuk membuat envelope ASDR
def create_asdr_envelope(duration, sample_rate, attack_time=0.2, decay_time=0.1, sustain_level=0.7, release_time=0.173):
total_samples = int(sample_rate * duration)
attack_samples = int(sample_rate * attack_time)
decay_samples = int(sample_rate * decay_time)
release_samples = int(sample_rate * release_time)
sustain_samples = total_samples - (attack_samples + decay_samples + release_samples)
attack = np.linspace(0, 1, attack_samples) # Attack (Naik dari 0 ke 1)
decay = np.linspace(1, sustain_level, decay_samples) # Decay (Turun dari 1 ke sustain_level
sustain = np.ones(sustain_samples) * sustain_level # Sustain (Tetap di sustain_level)
release = np.linspace(sustain_level, 0, release_samples) # Release (Turun dari sustain_level ke 0)
envelope = np.concatenate((attack, decay, sustain, release))
if len(envelope) < total_samples:
envelope = np.pad(envelope, (0, total_samples - len(envelope)), mode='constant')
elif len(envelope) > total_samples:
envelope = envelope[:total_samples]
return envelope
# Fungsi untuk membuat sweep dengan ASDR & normalisasi yang aman
def save_sweep_wave_asdr(start_freq, end_freq, duration, file_name, sample_rate=192000, gain_db=10):
try:
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
freqs = np.linspace(start_freq, end_freq, int(sample_rate * duration))
waveform = 0.5 * np.sin(2 * np.pi * freqs * t)
# Terapkan envelope ASDR
envelope = create_asdr_envelope(duration, sample_rate)
waveform *= envelope
# Konversi gain dB ke faktor pengali
gain_factor = 10 ** (gain_db / 20)
waveform *= gain_factor
# Normalisasi (hindari pembagian oleh nol)
max_value = np.max(np.abs(waveform))
if max_value > 0:
waveform = np.int16(waveform / max_value * 32767)
else:
waveform = np.zeros_like(waveform, dtype=np.int16)
# Simpan file audio
write(file_name, sample_rate, waveform)
print(f"✅ Audio sweep disimpan sebagai: {file_name}")
except Exception as e:
print(f"❌ Gagal menyimpan file: {e}")
# Simpan sweep dari 33KHz ke 77KHz selama 1/2 detik dengan ASDR
save_sweep_wave_asdr(33000, 77000, 1/2, "/storage/emulated/0/Music/Frequency_Sweep_ASDR.wav")
Comments
Post a Comment