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:

  1. 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, bukan 1, 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.

  2. Kesalahan Perhitungan Jumlah Sampel
    Kita hitung total sample berdasarkan parameter:

    total_samples = int(sample_rate * duration)  # 44100 * (1/3) = 14700 samples
    

    Attack, 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) = -2940
    

    Masalahnya adalah sustain_samples menjadi negatif, yang menyebabkan sustain = np.ones(sustain_samples) * sustain_level gagal, karena array tidak bisa memiliki panjang negatif.

    Solusi: Pastikan attack_time + decay_time + release_time <= duration, misalnya dengan menyesuaikan release_time.

  3. Kesalahan Normalisasi Gain
    Gain dihitung sebagai:

    gain_factor = 10 ** (gain_db / 10)
    

    Dengan gain_db = 10, maka:

    gain_factor = 10 ** (10 / 10) = 10
    

    Sehingga amplitudo diperbesar 10 kali lipat, menyebabkan clipping saat dikonversi ke np.int16, yang seharusnya berada dalam rentang -32767 hingga 32767.

    Solusi: Gunakan perhitungan gain dalam dB SPL (Sound Pressure Level):

    gain_factor = 10 ** (gain_db / 20)  # Lebih aman untuk skala amplitudo
    
  4. Frekuensi Sweep Terlalu Tinggi
    Sweep dilakukan dari 33kHz ke 77kHz, 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_rate ke 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:

  1. Kurangi release → Misalnya release = 0.133 detik, agar totalnya 0.333 detik.
  2. 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
Dengan frekwensi sampel_rate 44100 Hz menghasilkan audio wav dengan bunyi suara kedengaran membunyikan: cecak, cecak, cecak, ... dst.

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

Popular posts from this blog

Repellent Digital Tanpa Asdr

Modifikasi Rangkaian Rectifier Menjadi Repellent Nyamuk