Saya dapat menulis generator gelombang sinus dasar untuk audio, tetapi saya ingin dapat dengan lancar beralih dari satu frekuensi ke yang lain. Jika saya berhenti menghasilkan satu frekuensi dan segera beralih ke yang lain akan ada diskontinuitas dalam sinyal dan "klik" akan terdengar.
Pertanyaan saya adalah, apa algoritma yang baik untuk menghasilkan gelombang yang dimulai pada, katakanlah 250Hz, dan kemudian transisi ke 300Hz, tanpa memperkenalkan klik apa pun. Jika algoritma menyertakan waktu glide / portamento opsional, maka jauh lebih baik.
Saya dapat memikirkan beberapa pendekatan yang mungkin seperti oversampling diikuti oleh low pass filter, atau mungkin menggunakan wavetable, tapi saya yakin ini adalah masalah yang cukup umum sehingga ada cara standar untuk mengatasinya.
Jawaban:
Salah satu pendekatan yang saya gunakan di masa lalu adalah untuk mempertahankan akumulator fase yang digunakan sebagai indeks ke tabel pencarian gelombang. Nilai delta fase ditambahkan ke akumulator pada setiap interval sampel:
Untuk mengubah frekuensi Anda mengubah delta fase yang ditambahkan ke akumulator fase di setiap sampel, misalnya
dimana:
Ini menjamin bahwa bentuk gelombang output kontinu bahkan jika Anda mengubah fase_delta secara dinamis, misalnya untuk perubahan frekuensi, FM, dll.
Untuk perubahan frekuensi (portamento) yang lebih lancar, Anda dapat meningkatkan nilai phase_delta antara nilai lamanya dan nilai baru di atas jumlah interval sampel yang sesuai daripada hanya mengubahnya secara instan.
Perhatikan bahwa
phase_index
danphase_delta
keduanya memiliki bilangan bulat dan komponen fraksional, yaitu mereka harus floating point atau titik tetap. Bagian integer dari phase_index (ukuran tabel modulo) digunakan sebagai indeks ke dalam LUT gelombang, dan bagian fraksional dapat secara opsional digunakan untuk interpolasi antara nilai LUT yang berdekatan untuk output kualitas yang lebih tinggi dan / atau ukuran LUT yang lebih kecil.sumber
Salah satu cara terbaik untuk membuat gelombang sinus adalah dengan menggunakan fasor kompleks dengan pembaruan rekursif. Yaitu
Jadi kita dapat memeriksa sesekali jika itu masih terjadi dan memperbaikinya. Koreksi yang tepat adalah
jadi koreksi disederhanakan menjadi
Menerapkan koreksi sederhana ini setiap beberapa ratus sampel akan membuat osilator tetap stabil selamanya.
Untuk memvariasikan frekuensi secara terus menerus, pengali W perlu diperbarui. Bahkan perubahan non-kontinu pada pengali akan mempertahankan fungsi osilator kontinu. Jika peningkatan frekuensi diperlukan, pembaruan dapat dipecah menjadi beberapa langkah atau Anda dapat menggunakan algoritma osilator yang sama untuk memperbarui pengali itu sendiri (karena itu juga merupakan phasor kompleks gain gain).
sumber
Dari situs ini :
Kedengarannya seperti itu seharusnya bekerja.
(Sebenarnya, jika keduanya disinkronkan pada sumbu x pada transisi, saya kira transisi bertahap tidak diperlukan.)
sumber
Saya setuju dengan saran sebelumnya menggunakan akumulator fase. Pada dasarnya input kontrol adalah jumlah gerak maju per langkah atau per periode jam (atau per interupsi atau apa pun), sehingga mengubah nilai tersebut mengubah frekuensi tanpa diskontinuitas dalam fase. Amplitudo gelombang kemudian ditentukan dari nilai fase terakumulasi baik melalui LUT atau hanya perhitungan dosa (theta) atau cos (theta).
Ini pada dasarnya adalah apa yang umumnya dikenal sebagai Oscillator Controlled Oscillator (NCO) atau Direct Digital Synthesizer (DDS). Melakukan pencarian web pada istilah-istilah itu mungkin akan menghasilkan lebih dari yang Anda ingin tahu tentang teori dan praktik membuatnya bekerja dengan baik.
Menambahkan akumulator tambahan dapat memungkinkan transisi yang mulus antara frekuensi, seperti yang Anda sarankan, jika itu diinginkan juga, dengan mengendalikan laju perubahan nilai kenaikan fasa. Ini kadang-kadang disebut Penganalisis Diferensial Digital, atau DDA.
sumber
Urutan pertama, Anda harus menyesuaikan fase awal sinusoid frekuensi baru sehingga sama dengan fase sinusoid sebelumnya pada titik sampel transisi pertama. Hitung frekuensi pertama dan gunakan fase untuk frekuensi kedua.
Opsi 2 mungkin untuk meningkatkan d_phase dari satu frekuensi ke yang berikutnya melalui beberapa sampel. Ini akan membersihkan kontinuitas turunan pertama dan memberikan luncuran.
Pilihan ke-3 mungkin menggunakan jendela penghalusan, seperti peningkatan-cosinus, pada tingkat ramping d_phase.
sumber